• 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     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     rb_raise(rb_eLoadError, "no such file to load -- %s",
00554              RSTRING_PTR(fname));
00555 }
00556 
00557 static VALUE
00558 load_ext(VALUE path)
00559 {
00560     SCOPE_SET(NOEX_PUBLIC);
00561     return (VALUE)dln_load(RSTRING_PTR(path));
00562 }
00563 
00564 VALUE
00565 rb_require_safe(VALUE fname, int safe)
00566 {
00567     volatile VALUE result = Qnil;
00568     rb_thread_t *th = GET_THREAD();
00569     volatile VALUE errinfo = th->errinfo;
00570     int state;
00571     struct {
00572         int safe;
00573     } volatile saved;
00574     char *volatile ftptr = 0;
00575 
00576     PUSH_TAG();
00577     saved.safe = rb_safe_level();
00578     if ((state = EXEC_TAG()) == 0) {
00579         VALUE path;
00580         long handle;
00581         int found;
00582 
00583         rb_set_safe_level_force(safe);
00584         FilePathValue(fname);
00585         rb_set_safe_level_force(0);
00586         found = search_required(fname, &path, safe);
00587         if (found) {
00588             if (!path || !(ftptr = load_lock(RSTRING_PTR(path)))) {
00589                 result = Qfalse;
00590             }
00591             else {
00592                 switch (found) {
00593                   case 'r':
00594                     rb_load_internal(path, 0);
00595                     break;
00596 
00597                   case 's':
00598                     handle = (long)rb_vm_call_cfunc(rb_vm_top_self(), load_ext,
00599                                                     path, 0, path, path);
00600                     rb_ary_push(ruby_dln_librefs, LONG2NUM(handle));
00601                     break;
00602                 }
00603                 rb_provide_feature(path);
00604                 result = Qtrue;
00605             }
00606         }
00607     }
00608     POP_TAG();
00609     load_unlock(ftptr, !state);
00610 
00611     rb_set_safe_level_force(saved.safe);
00612     if (state) {
00613         JUMP_TAG(state);
00614     }
00615 
00616     if (NIL_P(result)) {
00617         load_failed(fname);
00618     }
00619 
00620     th->errinfo = errinfo;
00621 
00622     return result;
00623 }
00624 
00625 VALUE
00626 rb_require(const char *fname)
00627 {
00628     VALUE fn = rb_str_new2(fname);
00629     OBJ_FREEZE(fn);
00630     return rb_require_safe(fn, rb_safe_level());
00631 }
00632 
00633 static VALUE
00634 init_ext_call(VALUE arg)
00635 {
00636     SCOPE_SET(NOEX_PUBLIC);
00637     (*(void (*)(void))arg)();
00638     return Qnil;
00639 }
00640 
00641 void
00642 ruby_init_ext(const char *name, void (*init)(void))
00643 {
00644     if (load_lock(name)) {
00645         rb_vm_call_cfunc(rb_vm_top_self(), init_ext_call, (VALUE)init,
00646                          0, rb_str_new2(name), Qnil);
00647         rb_provide(name);
00648         load_unlock(name, 1);
00649     }
00650 }
00651 
00652 /*
00653  *  call-seq:
00654  *     mod.autoload(module, filename)   -> nil
00655  *
00656  *  Registers _filename_ to be loaded (using <code>Kernel::require</code>)
00657  *  the first time that _module_ (which may be a <code>String</code> or
00658  *  a symbol) is accessed in the namespace of _mod_.
00659  *
00660  *     module A
00661  *     end
00662  *     A.autoload(:B, "b")
00663  *     A::B.doit            # autoloads "b"
00664  */
00665 
00666 static VALUE
00667 rb_mod_autoload(VALUE mod, VALUE sym, VALUE file)
00668 {
00669     ID id = rb_to_id(sym);
00670 
00671     FilePathValue(file);
00672     rb_autoload(mod, id, RSTRING_PTR(file));
00673     return Qnil;
00674 }
00675 
00676 /*
00677  *  call-seq:
00678  *     mod.autoload?(name)   -> String or nil
00679  *
00680  *  Returns _filename_ to be loaded if _name_ is registered as
00681  *  +autoload+ in the namespace of _mod_.
00682  *
00683  *     module A
00684  *     end
00685  *     A.autoload(:B, "b")
00686  *     A.autoload?(:B)            #=> "b"
00687  */
00688 
00689 static VALUE
00690 rb_mod_autoload_p(VALUE mod, VALUE sym)
00691 {
00692     return rb_autoload_p(mod, rb_to_id(sym));
00693 }
00694 
00695 /*
00696  *  call-seq:
00697  *     autoload(module, filename)   -> nil
00698  *
00699  *  Registers _filename_ to be loaded (using <code>Kernel::require</code>)
00700  *  the first time that _module_ (which may be a <code>String</code> or
00701  *  a symbol) is accessed.
00702  *
00703  *     autoload(:MyModule, "/usr/local/lib/modules/my_module.rb")
00704  */
00705 
00706 static VALUE
00707 rb_f_autoload(VALUE obj, VALUE sym, VALUE file)
00708 {
00709     VALUE klass = rb_vm_cbase();
00710     if (NIL_P(klass)) {
00711         rb_raise(rb_eTypeError, "Can not set autoload on singleton class");
00712     }
00713     return rb_mod_autoload(klass, sym, file);
00714 }
00715 
00716 /*
00717  *  call-seq:
00718  *     autoload?(name)   -> String or nil
00719  *
00720  *  Returns _filename_ to be loaded if _name_ is registered as
00721  *  +autoload+.
00722  *
00723  *     autoload(:B, "b")
00724  *     autoload?(:B)            #=> "b"
00725  */
00726 
00727 static VALUE
00728 rb_f_autoload_p(VALUE obj, VALUE sym)
00729 {
00730     /* use rb_vm_cbase() as same as rb_f_autoload. */
00731     VALUE klass = rb_vm_cbase();
00732     if (NIL_P(klass)) {
00733         return Qnil;
00734     }
00735     return rb_mod_autoload_p(klass, sym);
00736 }
00737 
00738 void
00739 Init_load()
00740 {
00741 #undef rb_intern
00742 #define rb_intern(str) rb_intern2(str, strlen(str))
00743     rb_vm_t *vm = GET_VM();
00744     static const char var_load_path[] = "$:";
00745     ID id_load_path = rb_intern2(var_load_path, sizeof(var_load_path)-1);
00746 
00747     rb_define_hooked_variable(var_load_path, (VALUE*)vm, load_path_getter, rb_gvar_readonly_setter);
00748     rb_alias_variable(rb_intern("$-I"), id_load_path);
00749     rb_alias_variable(rb_intern("$LOAD_PATH"), id_load_path);
00750     vm->load_path = rb_ary_new();
00751 
00752     rb_define_virtual_variable("$\"", get_loaded_features, 0);
00753     rb_define_virtual_variable("$LOADED_FEATURES", get_loaded_features, 0);
00754     vm->loaded_features = rb_ary_new();
00755 
00756     rb_define_global_function("load", rb_f_load, -1);
00757     rb_define_global_function("require", rb_f_require, 1);
00758     rb_define_global_function("require_relative", rb_f_require_relative, 1);
00759     rb_define_method(rb_cModule, "autoload", rb_mod_autoload, 2);
00760     rb_define_method(rb_cModule, "autoload?", rb_mod_autoload_p, 1);
00761     rb_define_global_function("autoload", rb_f_autoload, 2);
00762     rb_define_global_function("autoload?", rb_f_autoload_p, 1);
00763 
00764     ruby_dln_librefs = rb_ary_new();
00765     rb_gc_register_mark_object(ruby_dln_librefs);
00766 }
00767 

Generated on Wed Sep 8 2010 09:55:55 for Ruby by  doxygen 1.7.1