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

Generated on Sat Jul 7 2012 15:29:19 for Ruby by  doxygen 1.7.1