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