2 * load methods from eval.c
5 #include "eval_intern.h"
7 VALUE ruby_dln_librefs
;
9 #define IS_RBEXT(e) (strcmp(e, ".rb") == 0)
10 #define IS_SOEXT(e) (strcmp(e, ".so") == 0 || strcmp(e, ".o") == 0)
12 #define IS_DLEXT(e) (strcmp(e, DLEXT) == 0 || strcmp(e, DLEXT2) == 0)
14 #define IS_DLEXT(e) (strcmp(e, DLEXT) == 0)
18 static const char *const loadable_ext
[] = {
27 rb_get_load_path(void)
29 VALUE load_path
= GET_VM()->load_path
;
30 VALUE ary
= rb_ary_new2(RARRAY_LEN(load_path
));
33 for (i
= 0; i
< RARRAY_LEN(load_path
); ++i
) {
34 rb_ary_push(ary
, rb_file_expand_path(RARRAY_PTR(load_path
)[i
], Qnil
));
40 load_path_getter(ID id
, rb_vm_t
*vm
)
46 get_loaded_features(void)
48 return GET_VM()->loaded_features
;
52 get_loading_table(void)
54 return GET_VM()->loading_table
;
58 loaded_feature_path(const char *name
, long vlen
, const char *feature
, long len
,
59 int type
, VALUE load_path
)
63 for (i
= 0; i
< RARRAY_LEN(load_path
); ++i
) {
64 VALUE p
= RARRAY_PTR(load_path
)[i
];
65 const char *s
= StringValuePtr(p
);
66 long n
= RSTRING_LEN(p
);
68 if (vlen
< n
+ len
+ 1) continue;
69 if (n
&& (strncmp(name
, s
, n
) || name
[n
] != '/')) continue;
70 if (strncmp(name
+ n
+ 1, feature
, len
)) continue;
71 if (name
[n
+len
+1] && name
[n
+len
+1] != '.') continue;
74 if (IS_DLEXT(&name
[n
+len
+1])) return p
;
77 if (IS_RBEXT(&name
[n
+len
+1])) return p
;
86 struct loaded_feature_searching
{
95 loaded_feature_path_i(st_data_t v
, st_data_t b
, st_data_t f
)
97 const char *s
= (const char *)v
;
98 struct loaded_feature_searching
*fp
= (struct loaded_feature_searching
*)f
;
99 VALUE p
= loaded_feature_path(s
, strlen(s
), fp
->name
, fp
->len
,
100 fp
->type
, fp
->load_path
);
101 if (!p
) return ST_CONTINUE
;
107 rb_feature_p(const char *feature
, const char *ext
, int rb
, int expanded
, const char **fn
)
109 VALUE v
, features
, p
, load_path
= 0;
111 long i
, len
, elen
, n
;
112 st_table
*loading_tbl
;
120 type
= rb
? 'r' : 's';
123 len
= strlen(feature
);
127 features
= get_loaded_features();
128 for (i
= 0; i
< RARRAY_LEN(features
); ++i
) {
129 v
= RARRAY_PTR(features
)[i
];
130 f
= StringValuePtr(v
);
131 if ((n
= RSTRING_LEN(v
)) < len
) continue;
132 if (strncmp(f
, feature
, len
) != 0) {
133 if (expanded
) continue;
134 if (!load_path
) load_path
= rb_get_load_path();
135 if (!(p
= loaded_feature_path(f
, n
, feature
, len
, type
, load_path
)))
137 f
+= RSTRING_LEN(p
) + 1;
139 if (!*(e
= f
+ len
)) {
143 if (*e
!= '.') continue;
144 if ((!rb
|| !ext
) && (IS_SOEXT(e
) || IS_DLEXT(e
))) {
147 if ((rb
|| !ext
) && (IS_RBEXT(e
))) {
151 loading_tbl
= get_loading_table();
155 struct loaded_feature_searching fs
;
159 fs
.load_path
= load_path
? load_path
: rb_get_load_path();
161 st_foreach(loading_tbl
, loaded_feature_path_i
, (st_data_t
)&fs
);
162 if ((f
= fs
.result
) != 0) {
167 if (st_get_key(loading_tbl
, (st_data_t
)feature
, &data
)) {
168 if (fn
) *fn
= (const char*)data
;
170 if (!ext
) return 'u';
171 return !IS_RBEXT(ext
) ? 's' : 'r';
177 if (ext
&& *ext
) return 0;
178 bufstr
= rb_str_tmp_new(len
+ DLEXT_MAXLEN
);
179 buf
= RSTRING_PTR(bufstr
);
180 MEMCPY(buf
, feature
, char, len
);
181 for (i
= 0; (e
= loadable_ext
[i
]) != 0; i
++) {
182 strncpy(buf
+ len
, e
, DLEXT_MAXLEN
+ 1);
183 if (st_get_key(loading_tbl
, (st_data_t
)buf
, &data
)) {
184 rb_str_resize(bufstr
, 0);
185 if (fn
) *fn
= (const char*)data
;
186 return i
? 's' : 'r';
189 rb_str_resize(bufstr
, 0);
196 rb_provided(const char *feature
)
198 const char *ext
= strrchr(feature
, '.');
199 volatile VALUE fullpath
= 0;
201 if (*feature
== '.' &&
202 (feature
[1] == '/' || strncmp(feature
+1, "./", 2) == 0)) {
203 fullpath
= rb_file_expand_path(rb_str_new2(feature
), Qnil
);
204 feature
= RSTRING_PTR(fullpath
);
206 if (ext
&& !strchr(ext
, '/')) {
208 if (rb_feature_p(feature
, ext
, Qtrue
, Qfalse
, 0)) return Qtrue
;
211 else if (IS_SOEXT(ext
) || IS_DLEXT(ext
)) {
212 if (rb_feature_p(feature
, ext
, Qfalse
, Qfalse
, 0)) return Qtrue
;
216 if (rb_feature_p(feature
, feature
+ strlen(feature
), Qtrue
, Qfalse
, 0))
222 rb_provide_feature(VALUE feature
)
224 rb_ary_push(get_loaded_features(), feature
);
228 rb_provide(const char *feature
)
230 rb_provide_feature(rb_str_new2(feature
));
233 NORETURN(static void load_failed(VALUE
));
236 rb_load(VALUE fname
, int wrap
)
240 rb_thread_t
*th
= GET_THREAD();
241 volatile VALUE wrapper
= th
->top_wrapper
;
242 volatile VALUE self
= th
->top_self
;
243 volatile int loaded
= Qfalse
;
244 volatile int mild_compile_error
;
246 rb_thread_t
*volatile th0
= th
;
249 FilePathValue(fname
);
250 fname
= rb_str_new4(fname
);
251 tmp
= rb_find_file(fname
);
255 RB_GC_GUARD(fname
) = rb_str_new4(tmp
);
257 th
->errinfo
= Qnil
; /* ensure */
260 rb_secure(4); /* should alter global state */
264 /* load in anonymous module as toplevel */
265 th
->top_self
= rb_obj_clone(rb_vm_top_self());
266 th
->top_wrapper
= rb_module_new();
267 rb_extend_object(th
->top_self
, th
->top_wrapper
);
270 mild_compile_error
= th
->mild_compile_error
;
277 th
->mild_compile_error
++;
278 node
= (NODE
*)rb_load_file(RSTRING_PTR(fname
));
280 iseq
= rb_iseq_new(node
, rb_str_new2("<top (required)>"),
281 fname
, Qfalse
, ISEQ_TYPE_TOP
);
282 th
->mild_compile_error
--;
289 fname
= RB_GC_GUARD(fname
);
291 th
->mild_compile_error
= mild_compile_error
;
293 th
->top_wrapper
= wrapper
;
296 rb_exc_raise(GET_THREAD()->errinfo
);
299 vm_jump_tag_but_local_jump(state
, Qundef
);
302 if (!NIL_P(GET_THREAD()->errinfo
)) {
303 /* exception during load */
304 rb_exc_raise(th
->errinfo
);
309 rb_load_protect(VALUE fname
, int wrap
, int *state
)
314 if ((status
= EXEC_TAG()) == 0) {
315 rb_load(fname
, wrap
);
324 * load(filename, wrap=false) => true
326 * Loads and executes the Ruby
327 * program in the file _filename_. If the filename does not
328 * resolve to an absolute path, the file is searched for in the library
329 * directories listed in <code>$:</code>. If the optional _wrap_
330 * parameter is +true+, the loaded script will be executed
331 * under an anonymous module, protecting the calling program's global
332 * namespace. In no circumstance will any local variables in the loaded
333 * file be propagated to the loading environment.
337 rb_f_load(int argc
, VALUE
*argv
)
341 rb_scan_args(argc
, argv
, "11", &fname
, &wrap
);
342 rb_load(fname
, RTEST(wrap
));
347 load_lock(const char *ftptr
)
350 st_table
*loading_tbl
= get_loading_table();
352 if (!loading_tbl
|| !st_lookup(loading_tbl
, (st_data_t
)ftptr
, &data
)) {
353 /* loading ruby library should be serialized. */
355 GET_VM()->loading_table
= loading_tbl
= st_init_strtable();
358 ftptr
= ruby_strdup(ftptr
);
359 data
= (st_data_t
)rb_barrier_new();
360 st_insert(loading_tbl
, (st_data_t
)ftptr
, data
);
361 return (char *)ftptr
;
363 return RTEST(rb_barrier_wait((VALUE
)data
)) ? (char *)ftptr
: 0;
367 load_unlock(const char *ftptr
)
370 st_data_t key
= (st_data_t
)ftptr
;
372 st_table
*loading_tbl
= get_loading_table();
374 if (st_delete(loading_tbl
, &key
, &data
)) {
376 rb_barrier_release((VALUE
)data
);
384 * require(string) => true or false
386 * Ruby tries to load the library named _string_, returning
387 * +true+ if successful. If the filename does not resolve to
388 * an absolute path, it will be searched for in the directories listed
389 * in <code>$:</code>. If the file has the extension ``.rb'', it is
390 * loaded as a source file; if the extension is ``.so'', ``.o'', or
391 * ``.dll'', or whatever the default shared library extension is on
392 * the current platform, Ruby loads the shared library as a Ruby
393 * extension. Otherwise, Ruby tries adding ``.rb'', ``.so'', and so on
394 * to the name. The name of the loaded feature is added to the array in
395 * <code>$"</code>. A feature will not be loaded if it's name already
396 * appears in <code>$"</code>. However, the file name is not converted
397 * to an absolute path, so that ``<code>require 'a';require
398 * './a'</code>'' will load <code>a.rb</code> twice.
400 * require "my-library.rb"
401 * require "db-driver"
405 rb_f_require(VALUE obj
, VALUE fname
)
407 return rb_require_safe(fname
, rb_safe_level());
411 search_required(VALUE fname
, volatile VALUE
*path
)
419 ext
= strrchr(ftptr
= RSTRING_PTR(fname
), '.');
420 if (ext
&& !strchr(ext
, '/')) {
422 if (rb_feature_p(ftptr
, ext
, Qtrue
, Qfalse
, &loading
)) {
423 if (loading
) *path
= rb_str_new2(loading
);
426 if ((tmp
= rb_find_file(fname
)) != 0) {
427 tmp
= rb_file_expand_path(tmp
, Qnil
);
428 ext
= strrchr(ftptr
= RSTRING_PTR(tmp
), '.');
429 if (!rb_feature_p(ftptr
, ext
, Qtrue
, Qtrue
, 0))
435 else if (IS_SOEXT(ext
)) {
436 if (rb_feature_p(ftptr
, ext
, Qfalse
, Qfalse
, &loading
)) {
437 if (loading
) *path
= rb_str_new2(loading
);
440 tmp
= rb_str_new(RSTRING_PTR(fname
), ext
- RSTRING_PTR(fname
));
443 if (rb_find_file_ext(&tmp
, loadable_ext
+ 1)) {
444 tmp
= rb_file_expand_path(tmp
, Qnil
);
445 ext
= strrchr(ftptr
= RSTRING_PTR(tmp
), '.');
446 if (!rb_feature_p(ftptr
, ext
, Qfalse
, Qtrue
, 0))
451 rb_str_cat2(tmp
, DLEXT
);
453 if ((tmp
= rb_find_file(tmp
)) != 0) {
454 tmp
= rb_file_expand_path(tmp
, Qnil
);
455 ext
= strrchr(ftptr
= RSTRING_PTR(tmp
), '.');
456 if (!rb_feature_p(ftptr
, ext
, Qfalse
, Qtrue
, 0))
462 else if (IS_DLEXT(ext
)) {
463 if (rb_feature_p(ftptr
, ext
, Qfalse
, Qfalse
, &loading
)) {
464 if (loading
) *path
= rb_str_new2(loading
);
467 if ((tmp
= rb_find_file(fname
)) != 0) {
468 tmp
= rb_file_expand_path(tmp
, Qnil
);
469 ext
= strrchr(ftptr
= RSTRING_PTR(tmp
), '.');
470 if (!rb_feature_p(ftptr
, ext
, Qfalse
, Qtrue
, 0))
476 else if ((ft
= rb_feature_p(ftptr
, 0, Qfalse
, Qfalse
, &loading
)) == 'r') {
477 if (loading
) *path
= rb_str_new2(loading
);
481 type
= rb_find_file_ext(&tmp
, loadable_ext
);
482 tmp
= rb_file_expand_path(tmp
, Qnil
);
487 ftptr
= RSTRING_PTR(tmp
);
488 return rb_feature_p(ftptr
, 0, Qfalse
, Qtrue
, 0);
494 ext
= strrchr(ftptr
= RSTRING_PTR(tmp
), '.');
495 if (rb_feature_p(ftptr
, ext
, !--type
, Qtrue
, &loading
) && !loading
)
499 return type
? 's' : 'r';
503 load_failed(VALUE fname
)
505 rb_raise(rb_eLoadError
, "no such file to load -- %s",
512 SCOPE_SET(NOEX_PUBLIC
);
513 return (VALUE
)dln_load(RSTRING_PTR(path
));
517 rb_require_safe(VALUE fname
, int safe
)
520 rb_thread_t
*th
= GET_THREAD();
521 volatile VALUE errinfo
= th
->errinfo
;
526 char *volatile ftptr
= 0;
529 saved
.safe
= rb_safe_level();
530 if ((state
= EXEC_TAG()) == 0) {
535 rb_set_safe_level_force(safe
);
536 FilePathValue(fname
);
537 RB_GC_GUARD(fname
) = rb_str_new4(fname
);
538 found
= search_required(fname
, &path
);
540 if (!path
|| !(ftptr
= load_lock(RSTRING_PTR(path
)))) {
544 rb_set_safe_level_force(0);
551 handle
= (long)rb_vm_call_cfunc(rb_vm_top_self(), load_ext
,
553 rb_ary_push(ruby_dln_librefs
, LONG2NUM(handle
));
556 rb_provide_feature(path
);
564 rb_set_safe_level_force(saved
.safe
);
573 th
->errinfo
= errinfo
;
579 rb_require(const char *fname
)
581 VALUE fn
= rb_str_new2(fname
);
583 return rb_require_safe(fn
, rb_safe_level());
587 init_ext_call(VALUE arg
)
589 SCOPE_SET(NOEX_PUBLIC
);
590 (*(void (*)(void))arg
)();
595 ruby_init_ext(const char *name
, void (*init
)(void))
597 if (load_lock(name
)) {
598 rb_vm_call_cfunc(rb_vm_top_self(), init_ext_call
, (VALUE
)init
,
599 0, rb_str_new2(name
));
607 * mod.autoload(name, filename) => nil
609 * Registers _filename_ to be loaded (using <code>Kernel::require</code>)
610 * the first time that _module_ (which may be a <code>String</code> or
611 * a symbol) is accessed in the namespace of _mod_.
615 * A.autoload(:B, "b")
616 * A::B.doit # autoloads "b"
620 rb_mod_autoload(VALUE mod
, VALUE sym
, VALUE file
)
622 ID id
= rb_to_id(sym
);
625 rb_autoload(mod
, id
, RSTRING_PTR(file
));
630 * MISSING: documentation
634 rb_mod_autoload_p(VALUE mod
, VALUE sym
)
636 return rb_autoload_p(mod
, rb_to_id(sym
));
641 * autoload(module, filename) => nil
643 * Registers _filename_ to be loaded (using <code>Kernel::require</code>)
644 * the first time that _module_ (which may be a <code>String</code> or
645 * a symbol) is accessed.
647 * autoload(:MyModule, "/usr/local/lib/modules/my_module.rb")
651 rb_f_autoload(VALUE obj
, VALUE sym
, VALUE file
)
653 VALUE klass
= rb_vm_cbase();
655 rb_raise(rb_eTypeError
, "Can not set autoload on singleton class");
657 return rb_mod_autoload(klass
, sym
, file
);
661 * MISSING: documentation
665 rb_f_autoload_p(VALUE obj
, VALUE sym
)
667 /* use rb_vm_cbase() as same as rb_f_autoload. */
668 VALUE klass
= rb_vm_cbase();
672 return rb_mod_autoload_p(klass
, sym
);
678 rb_vm_t
*vm
= GET_VM();
679 const char *var_load_path
= "$:";
680 ID id_load_path
= rb_intern(var_load_path
);
682 rb_define_hooked_variable(var_load_path
, (VALUE
*)GET_VM(), load_path_getter
, 0);
683 rb_alias_variable((rb_intern
)("$-I"), id_load_path
);
684 rb_alias_variable((rb_intern
)("$LOAD_PATH"), id_load_path
);
685 vm
->load_path
= rb_ary_new();
687 rb_define_virtual_variable("$\"", get_loaded_features
, 0);
688 rb_define_virtual_variable("$LOADED_FEATURES", get_loaded_features
, 0);
689 vm
->loaded_features
= rb_ary_new();
691 rb_define_global_function("load", rb_f_load
, -1);
692 rb_define_global_function("require", rb_f_require
, 1);
693 rb_define_method(rb_cModule
, "autoload", rb_mod_autoload
, 2);
694 rb_define_method(rb_cModule
, "autoload?", rb_mod_autoload_p
, 1);
695 rb_define_global_function("autoload", rb_f_autoload
, 2);
696 rb_define_global_function("autoload?", rb_f_autoload_p
, 1);
698 ruby_dln_librefs
= rb_ary_new();
699 rb_register_mark_object(ruby_dln_librefs
);