2 * load methods from eval.c
6 #include "eval_intern.h"
8 #include "internal/dir.h"
9 #include "internal/error.h"
10 #include "internal/file.h"
11 #include "internal/load.h"
12 #include "internal/parse.h"
13 #include "internal/thread.h"
14 #include "internal/variable.h"
17 #include "ruby/encoding.h"
18 #include "ruby/util.h"
20 static VALUE ruby_dln_librefs
;
22 #define IS_RBEXT(e) (strcmp((e), ".rb") == 0)
23 #define IS_SOEXT(e) (strcmp((e), ".so") == 0 || strcmp((e), ".o") == 0)
24 #define IS_DLEXT(e) (strcmp((e), DLEXT) == 0)
26 static const char *const loadable_ext
[] = {
31 static const char *const ruby_ext
[] = {
43 /* Construct expanded load path and store it to cache.
44 We rebuild load path partially if the cache is invalid.
45 We don't cache non string object and expand it every time. We ensure that
46 string objects in $LOAD_PATH are frozen.
49 rb_construct_expanded_load_path(rb_vm_t
*vm
, enum expand_type type
, int *has_relative
, int *has_non_cache
)
51 VALUE load_path
= vm
->load_path
;
52 VALUE expanded_load_path
= vm
->expanded_load_path
;
56 ary
= rb_ary_tmp_new(RARRAY_LEN(load_path
));
57 for (i
= 0; i
< RARRAY_LEN(load_path
); ++i
) {
58 VALUE path
, as_str
, expanded_path
;
59 int is_string
, non_cache
;
61 as_str
= path
= RARRAY_AREF(load_path
, i
);
62 is_string
= RB_TYPE_P(path
, T_STRING
) ? 1 : 0;
63 non_cache
= !is_string
? 1 : 0;
64 as_str
= rb_get_path_check_to_string(path
);
65 as_cstr
= RSTRING_PTR(as_str
);
68 if ((type
== EXPAND_RELATIVE
&&
69 rb_is_absolute_path(as_cstr
)) ||
70 (type
== EXPAND_HOME
&&
71 (!as_cstr
[0] || as_cstr
[0] != '~')) ||
72 (type
== EXPAND_NON_CACHE
)) {
73 /* Use cached expanded path. */
74 rb_ary_push(ary
, RARRAY_AREF(expanded_load_path
, i
));
78 if (!*has_relative
&& !rb_is_absolute_path(as_cstr
))
80 if (!*has_non_cache
&& non_cache
)
82 /* Freeze only string object. We expand other objects every time. */
85 as_str
= rb_get_path_check_convert(as_str
);
86 expanded_path
= rb_check_realpath(Qnil
, as_str
, NULL
);
87 if (NIL_P(expanded_path
)) expanded_path
= as_str
;
88 rb_ary_push(ary
, rb_fstring(expanded_path
));
91 vm
->expanded_load_path
= ary
;
92 rb_ary_replace(vm
->load_path_snapshot
, vm
->load_path
);
96 get_expanded_load_path(rb_vm_t
*vm
)
98 const VALUE non_cache
= Qtrue
;
100 if (!rb_ary_shared_with_p(vm
->load_path_snapshot
, vm
->load_path
)) {
101 /* The load path was modified. Rebuild the expanded load path. */
102 int has_relative
= 0, has_non_cache
= 0;
103 rb_construct_expanded_load_path(vm
, EXPAND_ALL
, &has_relative
, &has_non_cache
);
105 vm
->load_path_check_cache
= rb_dir_getwd_ospath();
107 else if (has_non_cache
) {
108 /* Non string object. */
109 vm
->load_path_check_cache
= non_cache
;
112 vm
->load_path_check_cache
= 0;
115 else if (vm
->load_path_check_cache
== non_cache
) {
116 int has_relative
= 1, has_non_cache
= 1;
117 /* Expand only non-cacheable objects. */
118 rb_construct_expanded_load_path(vm
, EXPAND_NON_CACHE
,
119 &has_relative
, &has_non_cache
);
121 else if (vm
->load_path_check_cache
) {
122 int has_relative
= 1, has_non_cache
= 1;
123 VALUE cwd
= rb_dir_getwd_ospath();
124 if (!rb_str_equal(vm
->load_path_check_cache
, cwd
)) {
125 /* Current working directory or filesystem encoding was changed.
126 Expand relative load path and non-cacheable objects again. */
127 vm
->load_path_check_cache
= cwd
;
128 rb_construct_expanded_load_path(vm
, EXPAND_RELATIVE
,
129 &has_relative
, &has_non_cache
);
132 /* Expand only tilde (User HOME) and non-cacheable objects. */
133 rb_construct_expanded_load_path(vm
, EXPAND_HOME
,
134 &has_relative
, &has_non_cache
);
137 return vm
->expanded_load_path
;
141 rb_get_expanded_load_path(void)
143 return get_expanded_load_path(GET_VM());
147 load_path_getter(ID id
, VALUE
* p
)
149 rb_vm_t
*vm
= (void *)p
;
150 return vm
->load_path
;
154 get_loaded_features(rb_vm_t
*vm
)
156 return vm
->loaded_features
;
160 get_loaded_features_realpaths(rb_vm_t
*vm
)
162 return vm
->loaded_features_realpaths
;
166 get_LOADED_FEATURES(ID _x
, VALUE
*_y
)
168 return get_loaded_features(GET_VM());
172 reset_loaded_features_snapshot(rb_vm_t
*vm
)
174 rb_ary_replace(vm
->loaded_features_snapshot
, vm
->loaded_features
);
177 static struct st_table
*
178 get_loaded_features_index_raw(rb_vm_t
*vm
)
180 return vm
->loaded_features_index
;
184 get_loading_table(rb_vm_t
*vm
)
186 return vm
->loading_table
;
190 feature_key(const char *str
, size_t len
)
192 return st_hash(str
, len
, 0xfea7009e);
196 is_rbext_path(VALUE feature_path
)
198 long len
= RSTRING_LEN(feature_path
);
199 long rbext_len
= rb_strlen_lit(".rb");
200 if (len
<= rbext_len
) return false;
201 return IS_RBEXT(RSTRING_PTR(feature_path
) + len
- rbext_len
);
205 features_index_add_single(rb_vm_t
*vm
, const char* str
, size_t len
, VALUE offset
, bool rb
)
207 struct st_table
*features_index
;
208 VALUE this_feature_index
= Qnil
;
209 st_data_t short_feature_key
;
212 Check_Type(offset
, T_FIXNUM
);
213 short_feature_key
= feature_key(str
, len
);
215 features_index
= get_loaded_features_index_raw(vm
);
216 if (!st_lookup(features_index
, short_feature_key
, &data
) ||
217 NIL_P(this_feature_index
= (VALUE
)data
)) {
218 st_insert(features_index
, short_feature_key
, (st_data_t
)offset
);
220 else if (FIXNUM_P(this_feature_index
)) {
221 VALUE loaded_features
= get_loaded_features(vm
);
222 VALUE this_feature_path
= RARRAY_AREF(loaded_features
, FIX2LONG(this_feature_index
));
223 VALUE feature_indexes
[2];
224 int top
= (rb
&& !is_rbext_path(this_feature_path
)) ? 1 : 0;
225 feature_indexes
[top
^0] = this_feature_index
;
226 feature_indexes
[top
^1] = offset
;
227 this_feature_index
= (VALUE
)xcalloc(1, sizeof(struct RArray
));
228 RBASIC(this_feature_index
)->flags
= T_ARRAY
; /* fake VALUE, do not mark/sweep */
229 rb_ary_cat(this_feature_index
, feature_indexes
, numberof(feature_indexes
));
230 st_insert(features_index
, short_feature_key
, (st_data_t
)this_feature_index
);
235 Check_Type(this_feature_index
, T_ARRAY
);
237 VALUE loaded_features
= get_loaded_features(vm
);
238 for (long i
= 0; i
< RARRAY_LEN(this_feature_index
); ++i
) {
239 VALUE idx
= RARRAY_AREF(this_feature_index
, i
);
240 VALUE this_feature_path
= RARRAY_AREF(loaded_features
, FIX2LONG(idx
));
241 Check_Type(this_feature_path
, T_STRING
);
242 if (!is_rbext_path(this_feature_path
)) {
243 /* as this_feature_index is a fake VALUE, `push` (which
244 * doesn't wb_unprotect like as rb_ary_splice) first,
245 * then rotate partially. */
251 rb_ary_push(this_feature_index
, offset
);
253 VALUE
*ptr
= (VALUE
*)RARRAY_CONST_PTR_TRANSIENT(this_feature_index
);
254 long len
= RARRAY_LEN(this_feature_index
);
255 MEMMOVE(ptr
+ pos
, ptr
+ pos
+ 1, VALUE
, len
- pos
- 1);
261 /* Add to the loaded-features index all the required entries for
262 `feature`, located at `offset` in $LOADED_FEATURES. We add an
263 index entry at each string `short_feature` for which
264 feature == "#{prefix}#{short_feature}#{ext}"
265 where `ext` is empty or matches %r{^\.[^./]*$}, and `prefix` is empty
266 or ends in '/'. This maintains the invariant that `rb_feature_p()`
267 relies on for its fast lookup.
270 features_index_add(rb_vm_t
*vm
, VALUE feature
, VALUE offset
)
272 const char *feature_str
, *feature_end
, *ext
, *p
;
275 feature_str
= StringValuePtr(feature
);
276 feature_end
= feature_str
+ RSTRING_LEN(feature
);
278 for (ext
= feature_end
; ext
> feature_str
; ext
--)
279 if (*ext
== '.' || *ext
== '/')
285 /* Now `ext` points to the only string matching %r{^\.[^./]*$} that is
286 at the end of `feature`, or is NULL if there is no such string. */
288 p
= ext
? ext
: feature_end
;
291 while (p
>= feature_str
&& *p
!= '/')
295 /* Now *p == '/'. We reach this point for every '/' in `feature`. */
296 features_index_add_single(vm
, p
+ 1, feature_end
- p
- 1, offset
, false);
298 features_index_add_single(vm
, p
+ 1, ext
- p
- 1, offset
, rb
);
301 features_index_add_single(vm
, feature_str
, feature_end
- feature_str
, offset
, false);
303 features_index_add_single(vm
, feature_str
, ext
- feature_str
, offset
, rb
);
308 loaded_features_index_clear_i(st_data_t key
, st_data_t val
, st_data_t arg
)
310 VALUE obj
= (VALUE
)val
;
311 if (!SPECIAL_CONST_P(obj
)) {
313 ruby_sized_xfree((void *)obj
, sizeof(struct RArray
));
319 get_loaded_features_index(rb_vm_t
*vm
)
324 if (!rb_ary_shared_with_p(vm
->loaded_features_snapshot
, vm
->loaded_features
)) {
325 /* The sharing was broken; something (other than us in rb_provide_feature())
326 modified loaded_features. Rebuild the index. */
327 st_foreach(vm
->loaded_features_index
, loaded_features_index_clear_i
, 0);
329 VALUE realpaths
= vm
->loaded_features_realpaths
;
330 rb_hash_clear(realpaths
);
331 features
= vm
->loaded_features
;
332 for (i
= 0; i
< RARRAY_LEN(features
); i
++) {
334 as_str
= entry
= rb_ary_entry(features
, i
);
336 as_str
= rb_fstring(rb_str_freeze(as_str
));
338 rb_ary_store(features
, i
, as_str
);
339 features_index_add(vm
, as_str
, INT2FIX(i
));
341 reset_loaded_features_snapshot(vm
);
343 features
= rb_ary_dup(vm
->loaded_features_snapshot
);
344 long j
= RARRAY_LEN(features
);
345 for (i
= 0; i
< j
; i
++) {
346 VALUE as_str
= rb_ary_entry(features
, i
);
347 VALUE realpath
= rb_check_realpath(Qnil
, as_str
, NULL
);
348 if (NIL_P(realpath
)) realpath
= as_str
;
349 rb_hash_aset(realpaths
, rb_fstring(realpath
), Qtrue
);
352 return vm
->loaded_features_index
;
355 /* This searches `load_path` for a value such that
356 name == "#{load_path[i]}/#{feature}"
357 if `feature` is a suffix of `name`, or otherwise
358 name == "#{load_path[i]}/#{feature}#{ext}"
359 for an acceptable string `ext`. It returns
360 `load_path[i].to_str` if found, else 0.
362 If type is 's', then `ext` is acceptable only if IS_DLEXT(ext);
363 if 'r', then only if IS_RBEXT(ext); otherwise `ext` may be absent
364 or have any value matching `%r{^\.[^./]*$}`.
367 loaded_feature_path(const char *name
, long vlen
, const char *feature
, long len
,
368 int type
, VALUE load_path
)
374 if (vlen
< len
+1) return 0;
375 if (strchr(feature
, '.') && !strncmp(name
+(vlen
-len
), feature
, len
)) {
379 for (e
= name
+ vlen
; name
!= e
&& *e
!= '.' && *e
!= '/'; --e
);
382 strncmp(e
-len
, feature
, len
))
384 plen
= e
- name
- len
;
386 if (plen
> 0 && name
[plen
-1] != '/') {
389 if (type
== 's' ? !IS_DLEXT(&name
[plen
+len
]) :
390 type
== 'r' ? !IS_RBEXT(&name
[plen
+len
]) :
394 /* Now name == "#{prefix}/#{feature}#{ext}" where ext is acceptable
395 (possibly empty) and prefix is some string of length plen. */
397 if (plen
> 0) --plen
; /* exclude '.' */
398 for (i
= 0; i
< RARRAY_LEN(load_path
); ++i
) {
399 VALUE p
= RARRAY_AREF(load_path
, i
);
400 const char *s
= StringValuePtr(p
);
401 long n
= RSTRING_LEN(p
);
403 if (n
!= plen
) continue;
404 if (n
&& strncmp(name
, s
, n
)) continue;
410 struct loaded_feature_searching
{
419 loaded_feature_path_i(st_data_t v
, st_data_t b
, st_data_t f
)
421 const char *s
= (const char *)v
;
422 struct loaded_feature_searching
*fp
= (struct loaded_feature_searching
*)f
;
423 VALUE p
= loaded_feature_path(s
, strlen(s
), fp
->name
, fp
->len
,
424 fp
->type
, fp
->load_path
);
425 if (!p
) return ST_CONTINUE
;
431 rb_feature_p(rb_vm_t
*vm
, const char *feature
, const char *ext
, int rb
, int expanded
, const char **fn
)
433 VALUE features
, this_feature_index
= Qnil
, v
, p
, load_path
= 0;
435 long i
, len
, elen
, n
;
436 st_table
*loading_tbl
, *features_index
;
444 len
= strlen(feature
) - elen
;
445 type
= rb
? 'r' : 's';
448 len
= strlen(feature
);
452 features
= get_loaded_features(vm
);
453 features_index
= get_loaded_features_index(vm
);
455 key
= feature_key(feature
, strlen(feature
));
456 /* We search `features` for an entry such that either
457 "#{features[i]}" == "#{load_path[j]}/#{feature}#{e}"
459 "#{features[i]}" == "#{feature}#{e}"
460 Here `e` is an "allowed" extension -- either empty or one
461 of the extensions accepted by IS_RBEXT, IS_SOEXT, or
462 IS_DLEXT. Further, if `ext && rb` then `IS_RBEXT(e)`,
463 and if `ext && !rb` then `IS_SOEXT(e) || IS_DLEXT(e)`.
465 If `expanded`, then only the latter form (without load_path[j])
466 is accepted. Otherwise either form is accepted, *unless* `ext`
467 is false and an otherwise-matching entry of the first form is
468 preceded by an entry of the form
469 "#{features[i2]}" == "#{load_path[j2]}/#{feature}#{e2}"
470 where `e2` matches %r{^\.[^./]*$} but is not an allowed extension.
471 After a "distractor" entry of this form, only entries of the
472 form "#{feature}#{e}" are accepted.
474 In `rb_provide_feature()` and `get_loaded_features_index()` we
475 maintain an invariant that the array `this_feature_index` will
476 point to every entry in `features` which has the form
477 "#{prefix}#{feature}#{e}"
478 where `e` is empty or matches %r{^\.[^./]*$}, and `prefix` is empty
479 or ends in '/'. This includes both match forms above, as well
480 as any distractors, so we may ignore all other entries in `features`.
482 if (st_lookup(features_index
, key
, &data
) && !NIL_P(this_feature_index
= (VALUE
)data
)) {
486 if (RB_TYPE_P(this_feature_index
, T_ARRAY
)) {
487 if (i
>= RARRAY_LEN(this_feature_index
)) break;
488 entry
= RARRAY_AREF(this_feature_index
, i
);
492 entry
= this_feature_index
;
494 index
= FIX2LONG(entry
);
496 v
= RARRAY_AREF(features
, index
);
497 f
= StringValuePtr(v
);
498 if ((n
= RSTRING_LEN(v
)) < len
) continue;
499 if (strncmp(f
, feature
, len
) != 0) {
500 if (expanded
) continue;
501 if (!load_path
) load_path
= get_expanded_load_path(vm
);
502 if (!(p
= loaded_feature_path(f
, n
, feature
, len
, type
, load_path
)))
505 f
+= RSTRING_LEN(p
) + 1;
507 if (!*(e
= f
+ len
)) {
511 if (*e
!= '.') continue;
512 if ((!rb
|| !ext
) && (IS_SOEXT(e
) || IS_DLEXT(e
))) {
515 if ((rb
|| !ext
) && (IS_RBEXT(e
))) {
521 loading_tbl
= get_loading_table(vm
);
524 struct loaded_feature_searching fs
;
528 fs
.load_path
= load_path
? load_path
: get_expanded_load_path(vm
);
530 st_foreach(loading_tbl
, loaded_feature_path_i
, (st_data_t
)&fs
);
531 if ((f
= fs
.result
) != 0) {
536 if (st_get_key(loading_tbl
, (st_data_t
)feature
, &data
)) {
537 if (fn
) *fn
= (const char*)data
;
543 static const char so_ext
[][4] = {
547 if (ext
&& *ext
) return 0;
548 bufstr
= rb_str_tmp_new(len
+ DLEXT_MAXLEN
);
549 buf
= RSTRING_PTR(bufstr
);
550 MEMCPY(buf
, feature
, char, len
);
551 for (i
= 0; (e
= loadable_ext
[i
]) != 0; i
++) {
552 strlcpy(buf
+ len
, e
, DLEXT_MAXLEN
+ 1);
553 if (st_get_key(loading_tbl
, (st_data_t
)buf
, &data
)) {
554 rb_str_resize(bufstr
, 0);
555 if (fn
) *fn
= (const char*)data
;
556 return i
? 's' : 'r';
559 for (i
= 0; i
< numberof(so_ext
); i
++) {
560 strlcpy(buf
+ len
, so_ext
[i
], DLEXT_MAXLEN
+ 1);
561 if (st_get_key(loading_tbl
, (st_data_t
)buf
, &data
)) {
562 rb_str_resize(bufstr
, 0);
563 if (fn
) *fn
= (const char*)data
;
567 rb_str_resize(bufstr
, 0);
572 if (!ext
) return 'u';
573 return !IS_RBEXT(ext
) ? 's' : 'r';
577 rb_provided(const char *feature
)
579 return rb_feature_provided(feature
, 0);
583 feature_provided(rb_vm_t
*vm
, const char *feature
, const char **loading
)
585 const char *ext
= strrchr(feature
, '.');
588 if (*feature
== '.' &&
589 (feature
[1] == '/' || strncmp(feature
+1, "./", 2) == 0)) {
590 fullpath
= rb_file_expand_path_fast(rb_get_path(rb_str_new2(feature
)), Qnil
);
591 feature
= RSTRING_PTR(fullpath
);
593 if (ext
&& !strchr(ext
, '/')) {
595 if (rb_feature_p(vm
, feature
, ext
, TRUE
, FALSE
, loading
)) return TRUE
;
598 else if (IS_SOEXT(ext
) || IS_DLEXT(ext
)) {
599 if (rb_feature_p(vm
, feature
, ext
, FALSE
, FALSE
, loading
)) return TRUE
;
603 if (rb_feature_p(vm
, feature
, 0, TRUE
, FALSE
, loading
))
605 RB_GC_GUARD(fullpath
);
610 rb_feature_provided(const char *feature
, const char **loading
)
612 return feature_provided(GET_VM(), feature
, loading
);
616 rb_provide_feature(rb_vm_t
*vm
, VALUE feature
)
620 features
= get_loaded_features(vm
);
621 if (OBJ_FROZEN(features
)) {
622 rb_raise(rb_eRuntimeError
,
623 "$LOADED_FEATURES is frozen; cannot append feature");
625 rb_str_freeze(feature
);
627 get_loaded_features_index(vm
);
628 rb_ary_push(features
, rb_fstring(feature
));
629 features_index_add(vm
, feature
, INT2FIX(RARRAY_LEN(features
)-1));
630 reset_loaded_features_snapshot(vm
);
634 rb_provide(const char *feature
)
636 rb_provide_feature(GET_VM(), rb_fstring_cstr(feature
));
639 NORETURN(static void load_failed(VALUE
));
642 load_iseq_eval(rb_execution_context_t
*ec
, VALUE fname
)
644 const rb_iseq_t
*iseq
= rb_iseq_load_iseq(fname
);
648 VALUE parser
= rb_parser_new();
649 rb_parser_set_context(parser
, NULL
, FALSE
);
650 ast
= (rb_ast_t
*)rb_parser_load_file(parser
, fname
);
651 iseq
= rb_iseq_new_top(&ast
->body
, rb_fstring_lit("<top (required)>"),
652 fname
, rb_realpath_internal(Qnil
, fname
, 1), NULL
);
655 rb_exec_event_hook_script_compiled(ec
, iseq
, Qnil
);
659 static inline enum ruby_tag_type
660 load_wrapping(rb_execution_context_t
*ec
, VALUE fname
, VALUE load_wrapper
)
662 enum ruby_tag_type state
;
663 rb_thread_t
*th
= rb_ec_thread_ptr(ec
);
664 volatile VALUE wrapper
= th
->top_wrapper
;
665 volatile VALUE self
= th
->top_self
;
666 #if !defined __GNUC__
667 rb_thread_t
*volatile th0
= th
;
670 ec
->errinfo
= Qnil
; /* ensure */
672 /* load in module as toplevel */
673 th
->top_self
= rb_obj_clone(rb_vm_top_self());
674 th
->top_wrapper
= load_wrapper
;
675 rb_extend_object(th
->top_self
, th
->top_wrapper
);
678 state
= EC_EXEC_TAG();
679 if (state
== TAG_NONE
) {
680 load_iseq_eval(ec
, fname
);
684 #if !defined __GNUC__
686 fname
= RB_GC_GUARD(fname
);
689 th
->top_wrapper
= wrapper
;
694 raise_load_if_failed(rb_execution_context_t
*ec
, enum ruby_tag_type state
)
697 rb_vm_jump_tag_but_local_jump(state
);
700 if (!NIL_P(ec
->errinfo
)) {
701 rb_exc_raise(ec
->errinfo
);
706 rb_load_internal(VALUE fname
, VALUE wrap
)
708 rb_execution_context_t
*ec
= GET_EC();
709 enum ruby_tag_type state
= TAG_NONE
;
711 if (!RB_TYPE_P(wrap
, T_MODULE
)) {
712 wrap
= rb_module_new();
714 state
= load_wrapping(ec
, fname
, wrap
);
717 load_iseq_eval(ec
, fname
);
719 raise_load_if_failed(ec
, state
);
723 rb_load(VALUE fname
, int wrap
)
725 VALUE tmp
= rb_find_file(FilePathValue(fname
));
726 if (!tmp
) load_failed(fname
);
727 rb_load_internal(tmp
, RBOOL(wrap
));
731 rb_load_protect(VALUE fname
, int wrap
, int *pstate
)
733 enum ruby_tag_type state
;
735 EC_PUSH_TAG(GET_EC());
736 if ((state
= EC_EXEC_TAG()) == TAG_NONE
) {
737 rb_load(fname
, wrap
);
741 if (state
!= TAG_NONE
) *pstate
= state
;
746 * load(filename, wrap=false) -> true
748 * Loads and executes the Ruby program in the file _filename_.
750 * If the filename is an absolute path (e.g. starts with '/'), the file
751 * will be loaded directly using the absolute path.
753 * If the filename is an explicit relative path (e.g. starts with './' or
754 * '../'), the file will be loaded using the relative path from the current
757 * Otherwise, the file will be searched for in the library
758 * directories listed in <code>$LOAD_PATH</code> (<code>$:</code>).
759 * If the file is found in a directory, it will attempt to load the file
760 * relative to that directory. If the file is not found in any of the
761 * directories in <code>$LOAD_PATH</code>, the file will be loaded using
762 * the relative path from the current directory.
764 * If the file doesn't exist when there is an attempt to load it, a
765 * LoadError will be raised.
767 * If the optional _wrap_ parameter is +true+, the loaded script will
768 * be executed under an anonymous module, protecting the calling
769 * program's global namespace. If the optional _wrap_ parameter is a
770 * module, the loaded script will be executed under the given module.
771 * In no circumstance will any local variables in the loaded file be
772 * propagated to the loading environment.
776 rb_f_load(int argc
, VALUE
*argv
, VALUE _
)
778 VALUE fname
, wrap
, path
, orig_fname
;
780 rb_scan_args(argc
, argv
, "11", &fname
, &wrap
);
782 orig_fname
= rb_get_path_check_to_string(fname
);
783 fname
= rb_str_encode_ospath(orig_fname
);
784 RUBY_DTRACE_HOOK(LOAD_ENTRY
, RSTRING_PTR(orig_fname
));
786 path
= rb_find_file(fname
);
788 if (!rb_file_load_ok(RSTRING_PTR(fname
)))
789 load_failed(orig_fname
);
792 rb_load_internal(path
, wrap
);
794 RUBY_DTRACE_HOOK(LOAD_RETURN
, RSTRING_PTR(orig_fname
));
800 load_lock(rb_vm_t
*vm
, const char *ftptr
, bool warn
)
803 st_table
*loading_tbl
= get_loading_table(vm
);
805 if (!st_lookup(loading_tbl
, (st_data_t
)ftptr
, &data
)) {
807 ftptr
= ruby_strdup(ftptr
);
808 data
= (st_data_t
)rb_thread_shield_new();
809 st_insert(loading_tbl
, (st_data_t
)ftptr
, data
);
810 return (char *)ftptr
;
812 else if (imemo_type_p(data
, imemo_memo
)) {
813 struct MEMO
*memo
= MEMO_CAST(data
);
814 void (*init
)(void) = memo
->u3
.func
;
815 data
= (st_data_t
)rb_thread_shield_new();
816 st_insert(loading_tbl
, (st_data_t
)ftptr
, data
);
821 VALUE warning
= rb_warning_string("loading in progress, circular require considered harmful - %s", ftptr
);
822 rb_backtrace_each(rb_str_append
, warning
);
823 rb_warning("%"PRIsVALUE
, warning
);
825 switch (rb_thread_shield_wait((VALUE
)data
)) {
830 return (char *)ftptr
;
834 release_thread_shield(st_data_t
*key
, st_data_t
*value
, st_data_t done
, int existing
)
836 VALUE thread_shield
= (VALUE
)*value
;
837 if (!existing
) return ST_STOP
;
839 rb_thread_shield_destroy(thread_shield
);
840 /* Delete the entry even if there are waiting threads, because they
841 * won't load the file and won't delete the entry. */
843 else if (rb_thread_shield_release(thread_shield
)) {
852 load_unlock(rb_vm_t
*vm
, const char *ftptr
, int done
)
855 st_data_t key
= (st_data_t
)ftptr
;
856 st_table
*loading_tbl
= get_loading_table(vm
);
858 st_update(loading_tbl
, key
, release_thread_shield
, done
);
865 * require(name) -> true or false
867 * Loads the given +name+, returning +true+ if successful and +false+ if the
868 * feature is already loaded.
870 * If the filename neither resolves to an absolute path nor starts with
871 * './' or '../', the file will be searched for in the library
872 * directories listed in <code>$LOAD_PATH</code> (<code>$:</code>).
873 * If the filename starts with './' or '../', resolution is based on Dir.pwd.
875 * If the filename has the extension ".rb", it is loaded as a source file; if
876 * the extension is ".so", ".o", or ".dll", or the default shared library
877 * extension on the current platform, Ruby loads the shared library as a
878 * Ruby extension. Otherwise, Ruby tries adding ".rb", ".so", and so on
879 * to the name until found. If the file named cannot be found, a LoadError
882 * For Ruby extensions the filename given may use any shared library
883 * extension. For example, on Linux the socket extension is "socket.so" and
884 * <code>require 'socket.dll'</code> will load the socket extension.
886 * The absolute path of the loaded file is added to
887 * <code>$LOADED_FEATURES</code> (<code>$"</code>). A file will not be
888 * loaded again if its path already appears in <code>$"</code>. For example,
889 * <code>require 'a'; require './a'</code> will not load <code>a.rb</code>
892 * require "my-library.rb"
893 * require "db-driver"
895 * Any constants or globals within the loaded source file will be available
896 * in the calling program's global namespace. However, local variables will
897 * not be propagated to the loading environment.
902 rb_f_require(VALUE obj
, VALUE fname
)
904 return rb_require_string(fname
);
909 * require_relative(string) -> true or false
911 * Ruby tries to load the library named _string_ relative to the requiring
912 * file's path. If the file's path cannot be determined a LoadError is raised.
913 * If a file is loaded +true+ is returned and false otherwise.
916 rb_f_require_relative(VALUE obj
, VALUE fname
)
918 VALUE base
= rb_current_realfilepath();
920 rb_loaderror("cannot infer basepath");
922 base
= rb_file_dirname(base
);
923 return rb_require_string(rb_file_absolute_path(fname
, base
));
926 typedef int (*feature_func
)(rb_vm_t
*vm
, const char *feature
, const char *ext
, int rb
, int expanded
, const char **fn
);
929 search_required(rb_vm_t
*vm
, VALUE fname
, volatile VALUE
*path
, feature_func rb_feature_p
)
937 ext
= strrchr(ftptr
= RSTRING_PTR(fname
), '.');
938 if (ext
&& !strchr(ext
, '/')) {
940 if (rb_feature_p(vm
, ftptr
, ext
, TRUE
, FALSE
, &loading
)) {
941 if (loading
) *path
= rb_filesystem_str_new_cstr(loading
);
944 if ((tmp
= rb_find_file(fname
)) != 0) {
945 ext
= strrchr(ftptr
= RSTRING_PTR(tmp
), '.');
946 if (!rb_feature_p(vm
, ftptr
, ext
, TRUE
, TRUE
, &loading
) || loading
)
952 else if (IS_SOEXT(ext
)) {
953 if (rb_feature_p(vm
, ftptr
, ext
, FALSE
, FALSE
, &loading
)) {
954 if (loading
) *path
= rb_filesystem_str_new_cstr(loading
);
957 tmp
= rb_str_subseq(fname
, 0, ext
- RSTRING_PTR(fname
));
958 rb_str_cat2(tmp
, DLEXT
);
960 if ((tmp
= rb_find_file(tmp
)) != 0) {
961 ext
= strrchr(ftptr
= RSTRING_PTR(tmp
), '.');
962 if (!rb_feature_p(vm
, ftptr
, ext
, FALSE
, TRUE
, &loading
) || loading
)
967 else if (IS_DLEXT(ext
)) {
968 if (rb_feature_p(vm
, ftptr
, ext
, FALSE
, FALSE
, &loading
)) {
969 if (loading
) *path
= rb_filesystem_str_new_cstr(loading
);
972 if ((tmp
= rb_find_file(fname
)) != 0) {
973 ext
= strrchr(ftptr
= RSTRING_PTR(tmp
), '.');
974 if (!rb_feature_p(vm
, ftptr
, ext
, FALSE
, TRUE
, &loading
) || loading
)
980 else if ((ft
= rb_feature_p(vm
, ftptr
, 0, FALSE
, FALSE
, &loading
)) == 'r') {
981 if (loading
) *path
= rb_filesystem_str_new_cstr(loading
);
985 type
= rb_find_file_ext(&tmp
, ft
== 's' ? ruby_ext
: loadable_ext
);
989 goto statically_linked
;
990 ftptr
= RSTRING_PTR(tmp
);
991 return rb_feature_p(vm
, ftptr
, 0, FALSE
, TRUE
, 0);
995 goto statically_linked
;
999 ext
= strrchr(ftptr
= RSTRING_PTR(tmp
), '.');
1000 if (rb_feature_p(vm
, ftptr
, ext
, !--type
, TRUE
, &loading
) && !loading
)
1004 return type
? 's' : 'r';
1007 if (loading
) *path
= rb_filesystem_str_new_cstr(loading
);
1012 load_failed(VALUE fname
)
1014 rb_load_fail(fname
, "cannot load such file");
1018 load_ext(VALUE path
)
1020 rb_scope_visibility_set(METHOD_VISI_PUBLIC
);
1021 return (VALUE
)dln_load(RSTRING_PTR(path
));
1025 no_feature_p(rb_vm_t
*vm
, const char *feature
, const char *ext
, int rb
, int expanded
, const char **fn
)
1030 // Documented in doc/globals.rdoc
1032 rb_resolve_feature_path(VALUE klass
, VALUE fname
)
1038 fname
= rb_get_path(fname
);
1039 path
= rb_str_encode_ospath(fname
);
1040 found
= search_required(GET_VM(), path
, &path
, no_feature_p
);
1044 sym
= ID2SYM(rb_intern("rb"));
1047 sym
= ID2SYM(rb_intern("so"));
1053 return rb_ary_new_from_args(2, sym
, path
);
1057 ext_config_push(rb_thread_t
*th
, struct rb_ext_config
*prev
)
1059 *prev
= th
->ext_config
;
1060 th
->ext_config
= (struct rb_ext_config
){0};
1064 ext_config_pop(rb_thread_t
*th
, struct rb_ext_config
*prev
)
1066 th
->ext_config
= *prev
;
1070 rb_ext_ractor_safe(bool flag
)
1072 GET_THREAD()->ext_config
.ractor_safe
= flag
;
1077 * 0: if already loaded (false)
1078 * 1: successfully loaded (true)
1079 * <0: not found (LoadError)
1083 require_internal(rb_execution_context_t
*ec
, VALUE fname
, int exception
, bool warn
)
1085 volatile int result
= -1;
1086 rb_thread_t
*th
= rb_ec_thread_ptr(ec
);
1087 volatile const struct {
1088 VALUE wrapper
, self
, errinfo
;
1090 th
->top_wrapper
, th
->top_self
, ec
->errinfo
,
1092 enum ruby_tag_type state
;
1093 char *volatile ftptr
= 0;
1095 volatile VALUE saved_path
;
1096 volatile VALUE realpath
= 0;
1097 VALUE realpaths
= get_loaded_features_realpaths(th
->vm
);
1098 volatile bool reset_ext_config
= false;
1099 struct rb_ext_config prev_ext_config
;
1101 fname
= rb_get_path(fname
);
1102 path
= rb_str_encode_ospath(fname
);
1103 RUBY_DTRACE_HOOK(REQUIRE_ENTRY
, RSTRING_PTR(fname
));
1107 ec
->errinfo
= Qnil
; /* ensure */
1108 th
->top_wrapper
= 0;
1109 if ((state
= EC_EXEC_TAG()) == TAG_NONE
) {
1113 RUBY_DTRACE_HOOK(FIND_REQUIRE_ENTRY
, RSTRING_PTR(fname
));
1114 found
= search_required(th
->vm
, path
, &saved_path
, rb_feature_p
);
1115 RUBY_DTRACE_HOOK(FIND_REQUIRE_RETURN
, RSTRING_PTR(fname
));
1119 if (!path
|| !(ftptr
= load_lock(th
->vm
, RSTRING_PTR(path
), warn
))) {
1123 result
= TAG_RETURN
;
1125 else if (RTEST(rb_hash_aref(realpaths
,
1126 realpath
= rb_realpath_internal(Qnil
, path
, 1)))) {
1132 load_iseq_eval(ec
, path
);
1136 reset_ext_config
= true;
1137 ext_config_push(th
, &prev_ext_config
);
1138 handle
= (long)rb_vm_call_cfunc(rb_vm_top_self(), load_ext
,
1139 path
, VM_BLOCK_HANDLER_NONE
, path
);
1140 rb_ary_push(ruby_dln_librefs
, LONG2NUM(handle
));
1143 result
= TAG_RETURN
;
1149 rb_thread_t
*th2
= rb_ec_thread_ptr(ec
);
1150 th2
->top_self
= saved
.self
;
1151 th2
->top_wrapper
= saved
.wrapper
;
1152 if (reset_ext_config
) ext_config_pop(th2
, &prev_ext_config
);
1155 if (ftptr
) load_unlock(th2
->vm
, RSTRING_PTR(path
), !state
);
1158 if (state
== TAG_FATAL
) {
1159 EC_JUMP_TAG(ec
, state
);
1161 else if (exception
) {
1162 /* usually state == TAG_RAISE only, except for
1163 * rb_iseq_load_iseq in load_iseq_eval case */
1164 VALUE exc
= rb_vm_make_jump_tag_but_local_jump(state
, Qundef
);
1165 if (!NIL_P(exc
)) ec
->errinfo
= exc
;
1168 else if (state
== TAG_RETURN
) {
1172 /* never TAG_RETURN */
1175 if (!NIL_P(ec
->errinfo
)) {
1176 if (!exception
) return TAG_RAISE
;
1177 rb_exc_raise(ec
->errinfo
);
1180 if (result
== TAG_RETURN
) {
1181 rb_provide_feature(th2
->vm
, path
);
1182 VALUE real
= realpath
;
1184 rb_hash_aset(realpaths
, rb_fstring(real
), Qtrue
);
1187 ec
->errinfo
= saved
.errinfo
;
1189 RUBY_DTRACE_HOOK(REQUIRE_RETURN
, RSTRING_PTR(fname
));
1195 rb_require_internal_silent(VALUE fname
)
1197 rb_execution_context_t
*ec
= GET_EC();
1198 return require_internal(ec
, fname
, 1, false);
1202 rb_require_internal(VALUE fname
)
1204 rb_execution_context_t
*ec
= GET_EC();
1205 return require_internal(ec
, fname
, 1, RTEST(ruby_verbose
));
1209 ruby_require_internal(const char *fname
, unsigned int len
)
1211 struct RString fake
;
1212 VALUE str
= rb_setup_fake_str(&fake
, fname
, len
, 0);
1213 rb_execution_context_t
*ec
= GET_EC();
1214 int result
= require_internal(ec
, str
, 0, RTEST(ruby_verbose
));
1215 rb_set_errinfo(Qnil
);
1216 return result
== TAG_RETURN
? 1 : result
? -1 : 0;
1220 rb_require_string(VALUE fname
)
1222 rb_execution_context_t
*ec
= GET_EC();
1223 int result
= require_internal(ec
, fname
, 1, RTEST(ruby_verbose
));
1225 if (result
> TAG_RETURN
) {
1226 EC_JUMP_TAG(ec
, result
);
1232 return RBOOL(result
);
1236 rb_require(const char *fname
)
1238 return rb_require_string(rb_str_new_cstr(fname
));
1242 register_init_ext(st_data_t
*key
, st_data_t
*value
, st_data_t init
, int existing
)
1244 const char *name
= (char *)*key
;
1246 /* already registered */
1247 rb_warn("%s is already registered", name
);
1250 *value
= (st_data_t
)MEMO_NEW(0, 0, init
);
1251 *key
= (st_data_t
)ruby_strdup(name
);
1256 RUBY_FUNC_EXPORTED
void
1257 ruby_init_ext(const char *name
, void (*init
)(void))
1259 rb_vm_t
*vm
= GET_VM();
1260 st_table
*loading_tbl
= get_loading_table(vm
);
1262 if (feature_provided(vm
, name
, 0))
1264 st_update(loading_tbl
, (st_data_t
)name
, register_init_ext
, (st_data_t
)init
);
1269 * mod.autoload(module, filename) -> nil
1271 * Registers _filename_ to be loaded (using Kernel::require)
1272 * the first time that _module_ (which may be a String or
1273 * a symbol) is accessed in the namespace of _mod_.
1277 * A.autoload(:B, "b")
1278 * A::B.doit # autoloads "b"
1282 rb_mod_autoload(VALUE mod
, VALUE sym
, VALUE file
)
1284 ID id
= rb_to_id(sym
);
1286 FilePathValue(file
);
1287 rb_autoload_str(mod
, id
, file
);
1293 * mod.autoload?(name, inherit=true) -> String or nil
1295 * Returns _filename_ to be loaded if _name_ is registered as
1296 * +autoload+ in the namespace of _mod_ or one of its ancestors.
1300 * A.autoload(:B, "b")
1301 * A.autoload?(:B) #=> "b"
1303 * If +inherit+ is false, the lookup only checks the autoloads in the receiver:
1306 * autoload :CONST, "const.rb"
1312 * B.autoload?(:CONST) #=> "const.rb", found in A (ancestor)
1313 * B.autoload?(:CONST, false) #=> nil, not found in B itself
1318 rb_mod_autoload_p(int argc
, VALUE
*argv
, VALUE mod
)
1320 int recur
= (rb_check_arity(argc
, 1, 2) == 1) ? TRUE
: RTEST(argv
[1]);
1321 VALUE sym
= argv
[0];
1323 ID id
= rb_check_id(&sym
);
1327 return rb_autoload_at_p(mod
, id
, recur
);
1332 * autoload(module, filename) -> nil
1334 * Registers _filename_ to be loaded (using Kernel::require)
1335 * the first time that _module_ (which may be a String or
1336 * a symbol) is accessed.
1338 * autoload(:MyModule, "/usr/local/lib/modules/my_module.rb")
1342 rb_f_autoload(VALUE obj
, VALUE sym
, VALUE file
)
1344 VALUE klass
= rb_class_real(rb_vm_cbase());
1346 rb_raise(rb_eTypeError
, "Can not set autoload on singleton class");
1348 return rb_mod_autoload(klass
, sym
, file
);
1353 * autoload?(name, inherit=true) -> String or nil
1355 * Returns _filename_ to be loaded if _name_ is registered as
1359 * autoload?(:B) #=> "b"
1363 rb_f_autoload_p(int argc
, VALUE
*argv
, VALUE obj
)
1365 /* use rb_vm_cbase() as same as rb_f_autoload. */
1366 VALUE klass
= rb_vm_cbase();
1370 return rb_mod_autoload_p(argc
, argv
, klass
);
1376 rb_vm_t
*vm
= GET_VM();
1377 static const char var_load_path
[] = "$:";
1378 ID id_load_path
= rb_intern2(var_load_path
, sizeof(var_load_path
)-1);
1380 rb_define_hooked_variable(var_load_path
, (VALUE
*)vm
, load_path_getter
, rb_gvar_readonly_setter
);
1381 rb_alias_variable(rb_intern_const("$-I"), id_load_path
);
1382 rb_alias_variable(rb_intern_const("$LOAD_PATH"), id_load_path
);
1383 vm
->load_path
= rb_ary_new();
1384 vm
->expanded_load_path
= rb_ary_tmp_new(0);
1385 vm
->load_path_snapshot
= rb_ary_tmp_new(0);
1386 vm
->load_path_check_cache
= 0;
1387 rb_define_singleton_method(vm
->load_path
, "resolve_feature_path", rb_resolve_feature_path
, 1);
1389 rb_define_virtual_variable("$\"", get_LOADED_FEATURES
, 0);
1390 rb_define_virtual_variable("$LOADED_FEATURES", get_LOADED_FEATURES
, 0);
1391 vm
->loaded_features
= rb_ary_new();
1392 vm
->loaded_features_snapshot
= rb_ary_tmp_new(0);
1393 vm
->loaded_features_index
= st_init_numtable();
1394 vm
->loaded_features_realpaths
= rb_hash_new();
1395 rb_obj_hide(vm
->loaded_features_realpaths
);
1397 rb_define_global_function("load", rb_f_load
, -1);
1398 rb_define_global_function("require", rb_f_require
, 1);
1399 rb_define_global_function("require_relative", rb_f_require_relative
, 1);
1400 rb_define_method(rb_cModule
, "autoload", rb_mod_autoload
, 2);
1401 rb_define_method(rb_cModule
, "autoload?", rb_mod_autoload_p
, -1);
1402 rb_define_global_function("autoload", rb_f_autoload
, 2);
1403 rb_define_global_function("autoload?", rb_f_autoload_p
, -1);
1405 ruby_dln_librefs
= rb_ary_tmp_new(0);
1406 rb_gc_register_mark_object(ruby_dln_librefs
);