• Main Page
  • Modules
  • Data Structures
  • Files
  • File List
  • Globals

load.c

Go to the documentation of this file.
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 

Generated on Thu Sep 8 2011 03:50:43 for Ruby by  doxygen 1.7.1