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