Ruby 1.9.3p327(2012-11-10revision37606)
|
00001 /* 00002 * load methods from eval.c 00003 */ 00004 00005 #include "ruby/ruby.h" 00006 #include "ruby/util.h" 00007 #include "internal.h" 00008 #include "dln.h" 00009 #include "eval_intern.h" 00010 00011 VALUE ruby_dln_librefs; 00012 00013 #define IS_RBEXT(e) (strcmp((e), ".rb") == 0) 00014 #define IS_SOEXT(e) (strcmp((e), ".so") == 0 || strcmp((e), ".o") == 0) 00015 #ifdef DLEXT2 00016 #define IS_DLEXT(e) (strcmp((e), DLEXT) == 0 || strcmp((e), DLEXT2) == 0) 00017 #else 00018 #define IS_DLEXT(e) (strcmp((e), DLEXT) == 0) 00019 #endif 00020 00021 00022 static const char *const loadable_ext[] = { 00023 ".rb", DLEXT, 00024 #ifdef DLEXT2 00025 DLEXT2, 00026 #endif 00027 0 00028 }; 00029 00030 VALUE 00031 rb_get_load_path(void) 00032 { 00033 VALUE load_path = GET_VM()->load_path; 00034 return load_path; 00035 } 00036 00037 VALUE 00038 rb_get_expanded_load_path(void) 00039 { 00040 VALUE load_path = rb_get_load_path(); 00041 VALUE ary; 00042 long i; 00043 00044 ary = rb_ary_new2(RARRAY_LEN(load_path)); 00045 for (i = 0; i < RARRAY_LEN(load_path); ++i) { 00046 VALUE path = rb_file_expand_path_fast(RARRAY_PTR(load_path)[i], Qnil); 00047 rb_str_freeze(path); 00048 rb_ary_push(ary, path); 00049 } 00050 rb_obj_freeze(ary); 00051 return ary; 00052 } 00053 00054 static VALUE 00055 load_path_getter(ID id, rb_vm_t *vm) 00056 { 00057 return vm->load_path; 00058 } 00059 00060 static VALUE 00061 get_loaded_features(void) 00062 { 00063 return GET_VM()->loaded_features; 00064 } 00065 00066 static st_table * 00067 get_loading_table(void) 00068 { 00069 return GET_VM()->loading_table; 00070 } 00071 00072 static VALUE 00073 loaded_feature_path(const char *name, long vlen, const char *feature, long len, 00074 int type, VALUE load_path) 00075 { 00076 long i; 00077 long plen; 00078 const char *e; 00079 00080 if(vlen < len) return 0; 00081 if (!strncmp(name+(vlen-len),feature,len)){ 00082 plen = vlen - len - 1; 00083 } else { 00084 for (e = name + vlen; name != e && *e != '.' && *e != '/'; --e); 00085 if (*e!='.' || 00086 e-name < len || 00087 strncmp(e-len,feature,len) ) 00088 return 0; 00089 plen = e - name - len - 1; 00090 } 00091 for (i = 0; i < RARRAY_LEN(load_path); ++i) { 00092 VALUE p = RARRAY_PTR(load_path)[i]; 00093 const char *s = StringValuePtr(p); 00094 long n = RSTRING_LEN(p); 00095 00096 if (n != plen ) continue; 00097 if (n && (strncmp(name, s, n) || name[n] != '/')) continue; 00098 switch (type) { 00099 case 's': 00100 if (IS_DLEXT(&name[n+len+1])) return p; 00101 break; 00102 case 'r': 00103 if (IS_RBEXT(&name[n+len+1])) return p; 00104 break; 00105 default: 00106 return p; 00107 } 00108 } 00109 return 0; 00110 } 00111 00112 struct loaded_feature_searching { 00113 const char *name; 00114 long len; 00115 int type; 00116 VALUE load_path; 00117 const char *result; 00118 }; 00119 00120 static int 00121 loaded_feature_path_i(st_data_t v, st_data_t b, st_data_t f) 00122 { 00123 const char *s = (const char *)v; 00124 struct loaded_feature_searching *fp = (struct loaded_feature_searching *)f; 00125 VALUE p = loaded_feature_path(s, strlen(s), fp->name, fp->len, 00126 fp->type, fp->load_path); 00127 if (!p) return ST_CONTINUE; 00128 fp->result = s; 00129 return ST_STOP; 00130 } 00131 00132 static int 00133 rb_feature_p(const char *feature, const char *ext, int rb, int expanded, const char **fn) 00134 { 00135 VALUE v, features, p, load_path = 0; 00136 const char *f, *e; 00137 long i, len, elen, n; 00138 st_table *loading_tbl; 00139 st_data_t data; 00140 int type; 00141 00142 if (fn) *fn = 0; 00143 if (ext) { 00144 elen = strlen(ext); 00145 len = strlen(feature) - elen; 00146 type = rb ? 'r' : 's'; 00147 } 00148 else { 00149 len = strlen(feature); 00150 elen = 0; 00151 type = 0; 00152 } 00153 features = get_loaded_features(); 00154 for (i = 0; i < RARRAY_LEN(features); ++i) { 00155 v = RARRAY_PTR(features)[i]; 00156 f = StringValuePtr(v); 00157 if ((n = RSTRING_LEN(v)) < len) continue; 00158 if (strncmp(f, feature, len) != 0) { 00159 if (expanded) continue; 00160 if (!load_path) load_path = rb_get_expanded_load_path(); 00161 if (!(p = loaded_feature_path(f, n, feature, len, type, load_path))) 00162 continue; 00163 expanded = 1; 00164 f += RSTRING_LEN(p) + 1; 00165 } 00166 if (!*(e = f + len)) { 00167 if (ext) continue; 00168 return 'u'; 00169 } 00170 if (*e != '.') continue; 00171 if ((!rb || !ext) && (IS_SOEXT(e) || IS_DLEXT(e))) { 00172 return 's'; 00173 } 00174 if ((rb || !ext) && (IS_RBEXT(e))) { 00175 return 'r'; 00176 } 00177 } 00178 loading_tbl = get_loading_table(); 00179 if (loading_tbl) { 00180 f = 0; 00181 if (!expanded) { 00182 struct loaded_feature_searching fs; 00183 fs.name = feature; 00184 fs.len = len; 00185 fs.type = type; 00186 fs.load_path = load_path ? load_path : rb_get_load_path(); 00187 fs.result = 0; 00188 st_foreach(loading_tbl, loaded_feature_path_i, (st_data_t)&fs); 00189 if ((f = fs.result) != 0) { 00190 if (fn) *fn = f; 00191 goto loading; 00192 } 00193 } 00194 if (st_get_key(loading_tbl, (st_data_t)feature, &data)) { 00195 if (fn) *fn = (const char*)data; 00196 loading: 00197 if (!ext) return 'u'; 00198 return !IS_RBEXT(ext) ? 's' : 'r'; 00199 } 00200 else { 00201 VALUE bufstr; 00202 char *buf; 00203 00204 if (ext && *ext) return 0; 00205 bufstr = rb_str_tmp_new(len + DLEXT_MAXLEN); 00206 buf = RSTRING_PTR(bufstr); 00207 MEMCPY(buf, feature, char, len); 00208 for (i = 0; (e = loadable_ext[i]) != 0; i++) { 00209 strlcpy(buf + len, e, DLEXT_MAXLEN + 1); 00210 if (st_get_key(loading_tbl, (st_data_t)buf, &data)) { 00211 rb_str_resize(bufstr, 0); 00212 if (fn) *fn = (const char*)data; 00213 return i ? 's' : 'r'; 00214 } 00215 } 00216 rb_str_resize(bufstr, 0); 00217 } 00218 } 00219 return 0; 00220 } 00221 00222 int 00223 rb_provided(const char *feature) 00224 { 00225 return rb_feature_provided(feature, 0); 00226 } 00227 00228 int 00229 rb_feature_provided(const char *feature, const char **loading) 00230 { 00231 const char *ext = strrchr(feature, '.'); 00232 volatile VALUE fullpath = 0; 00233 00234 if (*feature == '.' && 00235 (feature[1] == '/' || strncmp(feature+1, "./", 2) == 0)) { 00236 fullpath = rb_file_expand_path_fast(rb_str_new2(feature), Qnil); 00237 feature = RSTRING_PTR(fullpath); 00238 } 00239 if (ext && !strchr(ext, '/')) { 00240 if (IS_RBEXT(ext)) { 00241 if (rb_feature_p(feature, ext, TRUE, FALSE, loading)) return TRUE; 00242 return FALSE; 00243 } 00244 else if (IS_SOEXT(ext) || IS_DLEXT(ext)) { 00245 if (rb_feature_p(feature, ext, FALSE, FALSE, loading)) return TRUE; 00246 return FALSE; 00247 } 00248 } 00249 if (rb_feature_p(feature, 0, TRUE, FALSE, loading)) 00250 return TRUE; 00251 return FALSE; 00252 } 00253 00254 static void 00255 rb_provide_feature(VALUE feature) 00256 { 00257 if (OBJ_FROZEN(get_loaded_features())) { 00258 rb_raise(rb_eRuntimeError, 00259 "$LOADED_FEATURES is frozen; cannot append feature"); 00260 } 00261 rb_ary_push(get_loaded_features(), feature); 00262 } 00263 00264 void 00265 rb_provide(const char *feature) 00266 { 00267 rb_provide_feature(rb_usascii_str_new2(feature)); 00268 } 00269 00270 NORETURN(static void load_failed(VALUE)); 00271 00272 static void 00273 rb_load_internal(VALUE fname, int wrap) 00274 { 00275 int state; 00276 rb_thread_t *th = GET_THREAD(); 00277 volatile VALUE wrapper = th->top_wrapper; 00278 volatile VALUE self = th->top_self; 00279 volatile int loaded = FALSE; 00280 volatile int mild_compile_error; 00281 #ifndef __GNUC__ 00282 rb_thread_t *volatile th0 = th; 00283 #endif 00284 00285 th->errinfo = Qnil; /* ensure */ 00286 00287 if (!wrap) { 00288 rb_secure(4); /* should alter global state */ 00289 th->top_wrapper = 0; 00290 } 00291 else { 00292 /* load in anonymous module as toplevel */ 00293 th->top_self = rb_obj_clone(rb_vm_top_self()); 00294 th->top_wrapper = rb_module_new(); 00295 rb_extend_object(th->top_self, th->top_wrapper); 00296 } 00297 00298 mild_compile_error = th->mild_compile_error; 00299 PUSH_TAG(); 00300 state = EXEC_TAG(); 00301 if (state == 0) { 00302 NODE *node; 00303 VALUE iseq; 00304 00305 th->mild_compile_error++; 00306 node = (NODE *)rb_load_file(RSTRING_PTR(fname)); 00307 loaded = TRUE; 00308 iseq = rb_iseq_new_top(node, rb_str_new2("<top (required)>"), fname, rb_realpath_internal(Qnil, fname, 1), Qfalse); 00309 th->mild_compile_error--; 00310 rb_iseq_eval(iseq); 00311 } 00312 POP_TAG(); 00313 00314 #ifndef __GNUC__ 00315 th = th0; 00316 fname = RB_GC_GUARD(fname); 00317 #endif 00318 th->mild_compile_error = mild_compile_error; 00319 th->top_self = self; 00320 th->top_wrapper = wrapper; 00321 00322 if (!loaded && !FIXNUM_P(GET_THREAD()->errinfo)) { 00323 /* an error on loading don't include INT2FIX(TAG_FATAL) see r35625 */ 00324 rb_exc_raise(GET_THREAD()->errinfo); 00325 } 00326 if (state) { 00327 rb_vm_jump_tag_but_local_jump(state, Qundef); 00328 } 00329 00330 if (!NIL_P(GET_THREAD()->errinfo)) { 00331 /* exception during load */ 00332 rb_exc_raise(th->errinfo); 00333 } 00334 } 00335 00336 void 00337 rb_load(VALUE fname, int wrap) 00338 { 00339 VALUE tmp = rb_find_file(FilePathValue(fname)); 00340 if (!tmp) load_failed(fname); 00341 rb_load_internal(tmp, wrap); 00342 } 00343 00344 void 00345 rb_load_protect(VALUE fname, int wrap, int *state) 00346 { 00347 int status; 00348 00349 PUSH_TAG(); 00350 if ((status = EXEC_TAG()) == 0) { 00351 rb_load(fname, wrap); 00352 } 00353 POP_TAG(); 00354 if (state) 00355 *state = status; 00356 } 00357 00358 /* 00359 * call-seq: 00360 * load(filename, wrap=false) -> true 00361 * 00362 * Loads and executes the Ruby 00363 * program in the file _filename_. If the filename does not 00364 * resolve to an absolute path, the file is searched for in the library 00365 * directories listed in <code>$:</code>. If the optional _wrap_ 00366 * parameter is +true+, the loaded script will be executed 00367 * under an anonymous module, protecting the calling program's global 00368 * namespace. In no circumstance will any local variables in the loaded 00369 * file be propagated to the loading environment. 00370 */ 00371 00372 static VALUE 00373 rb_f_load(int argc, VALUE *argv) 00374 { 00375 VALUE fname, wrap, path; 00376 00377 rb_scan_args(argc, argv, "11", &fname, &wrap); 00378 path = rb_find_file(FilePathValue(fname)); 00379 if (!path) { 00380 if (!rb_file_load_ok(RSTRING_PTR(fname))) 00381 load_failed(fname); 00382 path = fname; 00383 } 00384 rb_load_internal(path, RTEST(wrap)); 00385 return Qtrue; 00386 } 00387 00388 static char * 00389 load_lock(const char *ftptr) 00390 { 00391 st_data_t data; 00392 st_table *loading_tbl = get_loading_table(); 00393 00394 if (!loading_tbl || !st_lookup(loading_tbl, (st_data_t)ftptr, &data)) { 00395 /* loading ruby library should be serialized. */ 00396 if (!loading_tbl) { 00397 GET_VM()->loading_table = loading_tbl = st_init_strtable(); 00398 } 00399 /* partial state */ 00400 ftptr = ruby_strdup(ftptr); 00401 data = (st_data_t)rb_barrier_new(); 00402 st_insert(loading_tbl, (st_data_t)ftptr, data); 00403 return (char *)ftptr; 00404 } 00405 if (RTEST(ruby_verbose)) { 00406 rb_warning("loading in progress, circular require considered harmful - %s", ftptr); 00407 rb_backtrace(); 00408 } 00409 return RTEST(rb_barrier_wait((VALUE)data)) ? (char *)ftptr : 0; 00410 } 00411 00412 static void 00413 load_unlock(const char *ftptr, int done) 00414 { 00415 if (ftptr) { 00416 st_data_t key = (st_data_t)ftptr; 00417 st_data_t data; 00418 st_table *loading_tbl = get_loading_table(); 00419 00420 if (st_delete(loading_tbl, &key, &data)) { 00421 VALUE barrier = (VALUE)data; 00422 xfree((char *)key); 00423 if (done) 00424 rb_barrier_destroy(barrier); 00425 else 00426 rb_barrier_release(barrier); 00427 } 00428 } 00429 } 00430 00431 00432 /* 00433 * call-seq: 00434 * require(name) -> true or false 00435 * 00436 * Loads the given +name+, returning +true+ if successful and +false+ if the 00437 * feature is already loaded. 00438 * 00439 * If the filename does not resolve to an absolute path, it will be searched 00440 * for in the directories listed in <code>$LOAD_PATH</code> (<code>$:</code>). 00441 * 00442 * If the filename has the extension ".rb", it is loaded as a source file; if 00443 * the extension is ".so", ".o", or ".dll", or the default shared library 00444 * extension on the current platform, Ruby loads the shared library as a 00445 * Ruby extension. Otherwise, Ruby tries adding ".rb", ".so", and so on 00446 * to the name until found. If the file named cannot be found, a LoadError 00447 * will be raised. 00448 * 00449 * For Ruby extensions the filename given may use any shared library 00450 * extension. For example, on Linux the socket extension is "socket.so" and 00451 * <code>require 'socket.dll'</code> will load the socket extension. 00452 * 00453 * The absolute path of the loaded file is added to 00454 * <code>$LOADED_FEATURES</code> (<code>$"</code>). A file will not be 00455 * loaded again if its path already appears in <code>$"</code>. For example, 00456 * <code>require 'a'; require './a'</code> will not load <code>a.rb</code> 00457 * again. 00458 * 00459 * require "my-library.rb" 00460 * require "db-driver" 00461 */ 00462 00463 VALUE 00464 rb_f_require(VALUE obj, VALUE fname) 00465 { 00466 return rb_require_safe(fname, rb_safe_level()); 00467 } 00468 00469 /* 00470 * call-seq: 00471 * require_relative(string) -> true or false 00472 * 00473 * Ruby tries to load the library named _string_ relative to the requiring 00474 * file's path. If the file's path cannot be determined a LoadError is raised. 00475 * If a file is loaded +true+ is returned and false otherwise. 00476 */ 00477 VALUE 00478 rb_f_require_relative(VALUE obj, VALUE fname) 00479 { 00480 VALUE base = rb_current_realfilepath(); 00481 if (NIL_P(base)) { 00482 rb_raise(rb_eLoadError, "cannot infer basepath"); 00483 } 00484 base = rb_file_dirname(base); 00485 return rb_require_safe(rb_file_absolute_path(fname, base), rb_safe_level()); 00486 } 00487 00488 static int 00489 search_required(VALUE fname, volatile VALUE *path, int safe_level) 00490 { 00491 VALUE tmp; 00492 char *ext, *ftptr; 00493 int type, ft = 0; 00494 const char *loading; 00495 00496 *path = 0; 00497 ext = strrchr(ftptr = RSTRING_PTR(fname), '.'); 00498 if (ext && !strchr(ext, '/')) { 00499 if (IS_RBEXT(ext)) { 00500 if (rb_feature_p(ftptr, ext, TRUE, FALSE, &loading)) { 00501 if (loading) *path = rb_filesystem_str_new_cstr(loading); 00502 return 'r'; 00503 } 00504 if ((tmp = rb_find_file_safe(fname, safe_level)) != 0) { 00505 ext = strrchr(ftptr = RSTRING_PTR(tmp), '.'); 00506 if (!rb_feature_p(ftptr, ext, TRUE, TRUE, &loading) || loading) 00507 *path = tmp; 00508 return 'r'; 00509 } 00510 return 0; 00511 } 00512 else if (IS_SOEXT(ext)) { 00513 if (rb_feature_p(ftptr, ext, FALSE, FALSE, &loading)) { 00514 if (loading) *path = rb_filesystem_str_new_cstr(loading); 00515 return 's'; 00516 } 00517 tmp = rb_str_subseq(fname, 0, ext - RSTRING_PTR(fname)); 00518 #ifdef DLEXT2 00519 OBJ_FREEZE(tmp); 00520 if (rb_find_file_ext_safe(&tmp, loadable_ext + 1, safe_level)) { 00521 ext = strrchr(ftptr = RSTRING_PTR(tmp), '.'); 00522 if (!rb_feature_p(ftptr, ext, FALSE, TRUE, &loading) || loading) 00523 *path = tmp; 00524 return 's'; 00525 } 00526 #else 00527 rb_str_cat2(tmp, DLEXT); 00528 OBJ_FREEZE(tmp); 00529 if ((tmp = rb_find_file_safe(tmp, safe_level)) != 0) { 00530 ext = strrchr(ftptr = RSTRING_PTR(tmp), '.'); 00531 if (!rb_feature_p(ftptr, ext, FALSE, TRUE, &loading) || loading) 00532 *path = tmp; 00533 return 's'; 00534 } 00535 #endif 00536 } 00537 else if (IS_DLEXT(ext)) { 00538 if (rb_feature_p(ftptr, ext, FALSE, FALSE, &loading)) { 00539 if (loading) *path = rb_filesystem_str_new_cstr(loading); 00540 return 's'; 00541 } 00542 if ((tmp = rb_find_file_safe(fname, safe_level)) != 0) { 00543 ext = strrchr(ftptr = RSTRING_PTR(tmp), '.'); 00544 if (!rb_feature_p(ftptr, ext, FALSE, TRUE, &loading) || loading) 00545 *path = tmp; 00546 return 's'; 00547 } 00548 } 00549 } 00550 else if ((ft = rb_feature_p(ftptr, 0, FALSE, FALSE, &loading)) == 'r') { 00551 if (loading) *path = rb_filesystem_str_new_cstr(loading); 00552 return 'r'; 00553 } 00554 tmp = fname; 00555 type = rb_find_file_ext_safe(&tmp, loadable_ext, safe_level); 00556 switch (type) { 00557 case 0: 00558 if (ft) 00559 break; 00560 ftptr = RSTRING_PTR(tmp); 00561 return rb_feature_p(ftptr, 0, FALSE, TRUE, 0); 00562 00563 default: 00564 if (ft) 00565 break; 00566 case 1: 00567 ext = strrchr(ftptr = RSTRING_PTR(tmp), '.'); 00568 if (rb_feature_p(ftptr, ext, !--type, TRUE, &loading) && !loading) 00569 break; 00570 *path = tmp; 00571 } 00572 return type ? 's' : 'r'; 00573 } 00574 00575 static void 00576 load_failed(VALUE fname) 00577 { 00578 VALUE mesg = rb_str_buf_new_cstr("cannot load such file -- "); 00579 rb_str_append(mesg, fname); /* should be ASCII compatible */ 00580 rb_exc_raise(rb_exc_new3(rb_eLoadError, mesg)); 00581 } 00582 00583 static VALUE 00584 load_ext(VALUE path) 00585 { 00586 SCOPE_SET(NOEX_PUBLIC); 00587 return (VALUE)dln_load(RSTRING_PTR(path)); 00588 } 00589 00590 VALUE 00591 rb_require_safe(VALUE fname, int safe) 00592 { 00593 volatile VALUE result = Qnil; 00594 rb_thread_t *th = GET_THREAD(); 00595 volatile VALUE errinfo = th->errinfo; 00596 int state; 00597 struct { 00598 int safe; 00599 } volatile saved; 00600 char *volatile ftptr = 0; 00601 00602 PUSH_TAG(); 00603 saved.safe = rb_safe_level(); 00604 if ((state = EXEC_TAG()) == 0) { 00605 VALUE path; 00606 long handle; 00607 int found; 00608 00609 rb_set_safe_level_force(safe); 00610 FilePathValue(fname); 00611 rb_set_safe_level_force(0); 00612 found = search_required(fname, &path, safe); 00613 if (found) { 00614 if (!path || !(ftptr = load_lock(RSTRING_PTR(path)))) { 00615 result = Qfalse; 00616 } 00617 else { 00618 switch (found) { 00619 case 'r': 00620 rb_load_internal(path, 0); 00621 break; 00622 00623 case 's': 00624 handle = (long)rb_vm_call_cfunc(rb_vm_top_self(), load_ext, 00625 path, 0, path); 00626 rb_ary_push(ruby_dln_librefs, LONG2NUM(handle)); 00627 break; 00628 } 00629 rb_provide_feature(path); 00630 result = Qtrue; 00631 } 00632 } 00633 } 00634 POP_TAG(); 00635 load_unlock(ftptr, !state); 00636 00637 rb_set_safe_level_force(saved.safe); 00638 if (state) { 00639 JUMP_TAG(state); 00640 } 00641 00642 if (NIL_P(result)) { 00643 load_failed(fname); 00644 } 00645 00646 th->errinfo = errinfo; 00647 00648 return result; 00649 } 00650 00651 VALUE 00652 rb_require(const char *fname) 00653 { 00654 VALUE fn = rb_str_new2(fname); 00655 OBJ_FREEZE(fn); 00656 return rb_require_safe(fn, rb_safe_level()); 00657 } 00658 00659 static VALUE 00660 init_ext_call(VALUE arg) 00661 { 00662 SCOPE_SET(NOEX_PUBLIC); 00663 (*(void (*)(void))arg)(); 00664 return Qnil; 00665 } 00666 00667 RUBY_FUNC_EXPORTED void 00668 ruby_init_ext(const char *name, void (*init)(void)) 00669 { 00670 if (load_lock(name)) { 00671 rb_vm_call_cfunc(rb_vm_top_self(), init_ext_call, (VALUE)init, 00672 0, rb_str_new2(name)); 00673 rb_provide(name); 00674 load_unlock(name, 1); 00675 } 00676 } 00677 00678 /* 00679 * call-seq: 00680 * mod.autoload(module, filename) -> nil 00681 * 00682 * Registers _filename_ to be loaded (using <code>Kernel::require</code>) 00683 * the first time that _module_ (which may be a <code>String</code> or 00684 * a symbol) is accessed in the namespace of _mod_. 00685 * 00686 * module A 00687 * end 00688 * A.autoload(:B, "b") 00689 * A::B.doit # autoloads "b" 00690 */ 00691 00692 static VALUE 00693 rb_mod_autoload(VALUE mod, VALUE sym, VALUE file) 00694 { 00695 ID id = rb_to_id(sym); 00696 00697 FilePathValue(file); 00698 rb_autoload(mod, id, RSTRING_PTR(file)); 00699 return Qnil; 00700 } 00701 00702 /* 00703 * call-seq: 00704 * mod.autoload?(name) -> String or nil 00705 * 00706 * Returns _filename_ to be loaded if _name_ is registered as 00707 * +autoload+ in the namespace of _mod_. 00708 * 00709 * module A 00710 * end 00711 * A.autoload(:B, "b") 00712 * A.autoload?(:B) #=> "b" 00713 */ 00714 00715 static VALUE 00716 rb_mod_autoload_p(VALUE mod, VALUE sym) 00717 { 00718 return rb_autoload_p(mod, rb_to_id(sym)); 00719 } 00720 00721 /* 00722 * call-seq: 00723 * autoload(module, filename) -> nil 00724 * 00725 * Registers _filename_ to be loaded (using <code>Kernel::require</code>) 00726 * the first time that _module_ (which may be a <code>String</code> or 00727 * a symbol) is accessed. 00728 * 00729 * autoload(:MyModule, "/usr/local/lib/modules/my_module.rb") 00730 */ 00731 00732 static VALUE 00733 rb_f_autoload(VALUE obj, VALUE sym, VALUE file) 00734 { 00735 VALUE klass = rb_class_real(rb_vm_cbase()); 00736 if (NIL_P(klass)) { 00737 rb_raise(rb_eTypeError, "Can not set autoload on singleton class"); 00738 } 00739 return rb_mod_autoload(klass, sym, file); 00740 } 00741 00742 /* 00743 * call-seq: 00744 * autoload?(name) -> String or nil 00745 * 00746 * Returns _filename_ to be loaded if _name_ is registered as 00747 * +autoload+. 00748 * 00749 * autoload(:B, "b") 00750 * autoload?(:B) #=> "b" 00751 */ 00752 00753 static VALUE 00754 rb_f_autoload_p(VALUE obj, VALUE sym) 00755 { 00756 /* use rb_vm_cbase() as same as rb_f_autoload. */ 00757 VALUE klass = rb_vm_cbase(); 00758 if (NIL_P(klass)) { 00759 return Qnil; 00760 } 00761 return rb_mod_autoload_p(klass, sym); 00762 } 00763 00764 void 00765 Init_load() 00766 { 00767 #undef rb_intern 00768 #define rb_intern(str) rb_intern2((str), strlen(str)) 00769 rb_vm_t *vm = GET_VM(); 00770 static const char var_load_path[] = "$:"; 00771 ID id_load_path = rb_intern2(var_load_path, sizeof(var_load_path)-1); 00772 00773 rb_define_hooked_variable(var_load_path, (VALUE*)vm, load_path_getter, rb_gvar_readonly_setter); 00774 rb_alias_variable(rb_intern("$-I"), id_load_path); 00775 rb_alias_variable(rb_intern("$LOAD_PATH"), id_load_path); 00776 vm->load_path = rb_ary_new(); 00777 00778 rb_define_virtual_variable("$\"", get_loaded_features, 0); 00779 rb_define_virtual_variable("$LOADED_FEATURES", get_loaded_features, 0); 00780 vm->loaded_features = rb_ary_new(); 00781 00782 rb_define_global_function("load", rb_f_load, -1); 00783 rb_define_global_function("require", rb_f_require, 1); 00784 rb_define_global_function("require_relative", rb_f_require_relative, 1); 00785 rb_define_method(rb_cModule, "autoload", rb_mod_autoload, 2); 00786 rb_define_method(rb_cModule, "autoload?", rb_mod_autoload_p, 1); 00787 rb_define_global_function("autoload", rb_f_autoload, 2); 00788 rb_define_global_function("autoload?", rb_f_autoload_p, 1); 00789 00790 ruby_dln_librefs = rb_ary_new(); 00791 rb_gc_register_mark_object(ruby_dln_librefs); 00792 } 00793