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"
21static VALUE ruby_dln_librefs;
23#define IS_RBEXT(e) (strcmp((e), ".rb") == 0)
24#define IS_SOEXT(e) (strcmp((e), ".so") == 0 || strcmp((e), ".o") == 0)
25#define IS_DLEXT(e) (strcmp((e), DLEXT) == 0)
27static const char *
const loadable_ext[] = {
32static const char *
const ruby_ext[] = {
50rb_construct_expanded_load_path(
rb_vm_t *vm,
enum expand_type
type,
int *has_relative,
int *has_non_cache)
52 VALUE load_path = vm->load_path;
53 VALUE expanded_load_path = vm->expanded_load_path;
57 ary = rb_ary_hidden_new(
RARRAY_LEN(load_path));
59 VALUE path, as_str, expanded_path;
60 int is_string, non_cache;
63 is_string = RB_TYPE_P(path,
T_STRING) ? 1 : 0;
64 non_cache = !is_string ? 1 : 0;
65 as_str = rb_get_path_check_to_string(path);
66 as_cstr = RSTRING_PTR(as_str);
69 if ((
type == EXPAND_RELATIVE &&
70 rb_is_absolute_path(as_cstr)) ||
71 (
type == EXPAND_HOME &&
72 (!as_cstr[0] || as_cstr[0] !=
'~')) ||
73 (
type == EXPAND_NON_CACHE)) {
75 rb_ary_push(ary,
RARRAY_AREF(expanded_load_path, i));
79 if (!*has_relative && !rb_is_absolute_path(as_cstr))
81 if (!*has_non_cache && non_cache)
86 as_str = rb_get_path_check_convert(as_str);
87 expanded_path = rb_check_realpath(
Qnil, as_str, NULL);
88 if (
NIL_P(expanded_path)) expanded_path = as_str;
89 rb_ary_push(ary, rb_fstring(expanded_path));
92 vm->expanded_load_path = ary;
93 rb_ary_replace(vm->load_path_snapshot, vm->load_path);
97get_expanded_load_path(
rb_vm_t *vm)
101 if (!rb_ary_shared_with_p(vm->load_path_snapshot, vm->load_path)) {
103 int has_relative = 0, has_non_cache = 0;
104 rb_construct_expanded_load_path(vm, EXPAND_ALL, &has_relative, &has_non_cache);
106 vm->load_path_check_cache = rb_dir_getwd_ospath();
108 else if (has_non_cache) {
110 vm->load_path_check_cache = non_cache;
113 vm->load_path_check_cache = 0;
116 else if (vm->load_path_check_cache == non_cache) {
117 int has_relative = 1, has_non_cache = 1;
119 rb_construct_expanded_load_path(vm, EXPAND_NON_CACHE,
120 &has_relative, &has_non_cache);
122 else if (vm->load_path_check_cache) {
123 int has_relative = 1, has_non_cache = 1;
124 VALUE cwd = rb_dir_getwd_ospath();
128 vm->load_path_check_cache = cwd;
129 rb_construct_expanded_load_path(vm, EXPAND_RELATIVE,
130 &has_relative, &has_non_cache);
134 rb_construct_expanded_load_path(vm, EXPAND_HOME,
135 &has_relative, &has_non_cache);
138 return vm->expanded_load_path;
142rb_get_expanded_load_path(
void)
144 return get_expanded_load_path(GET_VM());
148load_path_getter(
ID id,
VALUE * p)
151 return vm->load_path;
155get_loaded_features(
rb_vm_t *vm)
157 return vm->loaded_features;
161get_loaded_features_realpaths(
rb_vm_t *vm)
163 return vm->loaded_features_realpaths;
167get_LOADED_FEATURES(
ID _x,
VALUE *_y)
169 return get_loaded_features(GET_VM());
173reset_loaded_features_snapshot(
rb_vm_t *vm)
175 rb_ary_replace(vm->loaded_features_snapshot, vm->loaded_features);
179get_loaded_features_index_raw(
rb_vm_t *vm)
181 return vm->loaded_features_index;
187 return vm->loading_table;
191feature_key(
const char *str,
size_t len)
193 return st_hash(str, len, 0xfea7009e);
197is_rbext_path(
VALUE feature_path)
199 long len = RSTRING_LEN(feature_path);
201 if (len <= rbext_len)
return false;
202 return IS_RBEXT(RSTRING_PTR(feature_path) + len - rbext_len);
205typedef rb_darray(
long) feature_indexes_t;
207struct features_index_add_single_args {
214features_index_add_single_callback(st_data_t *key, st_data_t *value, st_data_t raw_args,
int existing)
216 struct features_index_add_single_args *args = (
struct features_index_add_single_args *)raw_args;
218 VALUE offset = args->offset;
222 VALUE this_feature_index = *value;
225 VALUE loaded_features = get_loaded_features(vm);
228 feature_indexes_t feature_indexes;
229 rb_darray_make(&feature_indexes, 2);
230 int top = (rb && !is_rbext_path(this_feature_path)) ? 1 : 0;
231 rb_darray_set(feature_indexes, top^0,
FIX2LONG(this_feature_index));
232 rb_darray_set(feature_indexes, top^1,
FIX2LONG(offset));
234 assert(rb_darray_size(feature_indexes) == 2);
238 *value = (st_data_t)feature_indexes;
241 feature_indexes_t feature_indexes = (feature_indexes_t)this_feature_index;
245 VALUE loaded_features = get_loaded_features(vm);
246 for (
size_t i = 0; i < rb_darray_size(feature_indexes); ++i) {
247 long idx = rb_darray_get(feature_indexes, i);
249 Check_Type(this_feature_path,
T_STRING);
250 if (!is_rbext_path(this_feature_path)) {
257 rb_darray_append(&feature_indexes,
FIX2LONG(offset));
259 *value = (st_data_t)feature_indexes;
262 long *ptr = rb_darray_data_ptr(feature_indexes);
263 long len = rb_darray_size(feature_indexes);
264 MEMMOVE(ptr + pos, ptr + pos + 1,
long, len - pos - 1);
277features_index_add_single(
rb_vm_t *vm,
const char* str,
size_t len,
VALUE offset,
bool rb)
280 st_data_t short_feature_key;
283 short_feature_key = feature_key(str, len);
285 features_index = get_loaded_features_index_raw(vm);
287 struct features_index_add_single_args args = {
293 st_update(features_index, short_feature_key, features_index_add_single_callback, (st_data_t)&args);
307 const char *feature_str, *feature_end, *ext, *p;
311 feature_end = feature_str + RSTRING_LEN(feature);
313 for (ext = feature_end; ext > feature_str; ext--)
314 if (*ext ==
'.' || *ext ==
'/')
323 p = ext ? ext : feature_end;
326 while (p >= feature_str && *p !=
'/')
331 features_index_add_single(vm, p + 1, feature_end - p - 1, offset,
false);
333 features_index_add_single(vm, p + 1, ext - p - 1, offset, rb);
336 features_index_add_single(vm, feature_str, feature_end - feature_str, offset,
false);
338 features_index_add_single(vm, feature_str, ext - feature_str, offset, rb);
343loaded_features_index_clear_i(st_data_t key, st_data_t val, st_data_t arg)
347 rb_darray_free((
void *)obj);
353get_loaded_features_index(
rb_vm_t *vm)
358 if (!rb_ary_shared_with_p(vm->loaded_features_snapshot, vm->loaded_features)) {
361 st_foreach(vm->loaded_features_index, loaded_features_index_clear_i, 0);
363 VALUE realpaths = vm->loaded_features_realpaths;
364 rb_hash_clear(realpaths);
365 features = vm->loaded_features;
368 as_str = entry = rb_ary_entry(features, i);
372 rb_ary_store(features, i, as_str);
373 features_index_add(vm, as_str,
INT2FIX(i));
375 reset_loaded_features_snapshot(vm);
377 features = rb_ary_dup(vm->loaded_features_snapshot);
379 for (i = 0; i < j; i++) {
380 VALUE as_str = rb_ary_entry(features, i);
381 VALUE realpath = rb_check_realpath(
Qnil, as_str, NULL);
382 if (
NIL_P(realpath)) realpath = as_str;
383 rb_hash_aset(realpaths, rb_fstring(realpath),
Qtrue);
386 return vm->loaded_features_index;
401loaded_feature_path(
const char *name,
long vlen,
const char *feature,
long len,
408 if (vlen < len+1)
return 0;
409 if (strchr(feature,
'.') && !strncmp(name+(vlen-len), feature, len)) {
413 for (e = name + vlen; name != e && *e !=
'.' && *e !=
'/'; --e);
416 strncmp(e-len, feature, len))
418 plen = e - name - len;
420 if (plen > 0 && name[plen-1] !=
'/') {
423 if (
type ==
's' ? !IS_DLEXT(&name[plen+len]) :
424 type ==
'r' ? !IS_RBEXT(&name[plen+len]) :
431 if (plen > 0) --plen;
435 long n = RSTRING_LEN(p);
437 if (n != plen)
continue;
438 if (n && strncmp(name, s, n))
continue;
453loaded_feature_path_i(st_data_t v, st_data_t b, st_data_t f)
455 const char *s = (
const char *)v;
457 VALUE p = loaded_feature_path(s, strlen(s), fp->name, fp->len,
458 fp->type, fp->load_path);
459 if (!p)
return ST_CONTINUE;
465rb_feature_p(
rb_vm_t *vm,
const char *feature,
const char *ext,
int rb,
int expanded,
const char **fn)
467 VALUE features, this_feature_index =
Qnil, v, p, load_path = 0;
469 long i, len, elen, n;
470 st_table *loading_tbl, *features_index;
478 len = strlen(feature) - elen;
479 type = rb ?
'r' :
's';
482 len = strlen(feature);
486 features = get_loaded_features(vm);
487 features_index = get_loaded_features_index(vm);
489 key = feature_key(feature, strlen(feature));
516 if (st_lookup(features_index, key, &data) && !
NIL_P(this_feature_index = (
VALUE)data)) {
517 for (
size_t i = 0; ; i++) {
521 index =
FIX2LONG(this_feature_index);
524 feature_indexes_t feature_indexes = (feature_indexes_t)this_feature_index;
525 if (i >= rb_darray_size(feature_indexes))
break;
526 index = rb_darray_get(feature_indexes, i);
531 if ((n = RSTRING_LEN(v)) < len)
continue;
532 if (strncmp(f, feature, len) != 0) {
533 if (expanded)
continue;
534 if (!load_path) load_path = get_expanded_load_path(vm);
535 if (!(p = loaded_feature_path(f, n, feature, len,
type, load_path)))
538 f += RSTRING_LEN(p) + 1;
540 if (!*(e = f + len)) {
544 if (*e !=
'.')
continue;
545 if ((!rb || !ext) && (IS_SOEXT(e) || IS_DLEXT(e))) {
548 if ((rb || !ext) && (IS_RBEXT(e))) {
554 loading_tbl = get_loading_table(vm);
561 fs.load_path = load_path ? load_path : get_expanded_load_path(vm);
563 st_foreach(loading_tbl, loaded_feature_path_i, (st_data_t)&fs);
564 if ((f = fs.result) != 0) {
569 if (st_get_key(loading_tbl, (st_data_t)feature, &data)) {
570 if (fn) *fn = (
const char*)data;
576 static const char so_ext[][4] = {
580 if (ext && *ext)
return 0;
582 buf = RSTRING_PTR(bufstr);
583 MEMCPY(buf, feature,
char, len);
584 for (i = 0; (e = loadable_ext[i]) != 0; i++) {
585 strlcpy(buf + len, e, DLEXT_MAXLEN + 1);
586 if (st_get_key(loading_tbl, (st_data_t)buf, &data)) {
588 if (fn) *fn = (
const char*)data;
589 return i ?
's' :
'r';
592 for (i = 0; i < numberof(so_ext); i++) {
593 strlcpy(buf + len, so_ext[i], DLEXT_MAXLEN + 1);
594 if (st_get_key(loading_tbl, (st_data_t)buf, &data)) {
596 if (fn) *fn = (
const char*)data;
605 if (!ext)
return 'u';
606 return !IS_RBEXT(ext) ?
's' :
'r';
616feature_provided(
rb_vm_t *vm,
const char *feature,
const char **loading)
618 const char *ext = strrchr(feature,
'.');
621 if (*feature ==
'.' &&
622 (feature[1] ==
'/' || strncmp(feature+1,
"./", 2) == 0)) {
623 fullpath = rb_file_expand_path_fast(rb_get_path(
rb_str_new2(feature)),
Qnil);
624 feature = RSTRING_PTR(fullpath);
626 if (ext && !strchr(ext,
'/')) {
628 if (rb_feature_p(vm, feature, ext, TRUE, FALSE, loading))
return TRUE;
631 else if (IS_SOEXT(ext) || IS_DLEXT(ext)) {
632 if (rb_feature_p(vm, feature, ext, FALSE, FALSE, loading))
return TRUE;
636 if (rb_feature_p(vm, feature, 0, TRUE, FALSE, loading))
645 return feature_provided(GET_VM(), feature, loading);
653 features = get_loaded_features(vm);
656 "$LOADED_FEATURES is frozen; cannot append feature");
660 get_loaded_features_index(vm);
664 rb_ary_clear(vm->loaded_features_snapshot);
665 rb_ary_push(features, rb_fstring(feature));
667 reset_loaded_features_snapshot(vm);
673 rb_provide_feature(GET_VM(), rb_fstring_cstr(feature));
676NORETURN(
static void load_failed(
VALUE));
681 const rb_iseq_t *iseq = rb_iseq_load_iseq(fname);
685 VALUE v = rb_vm_push_frame_fname(ec, fname);
687 VALUE parser = rb_parser_new();
688 rb_parser_set_context(parser, NULL, FALSE);
689 ast = (
rb_ast_t *)rb_parser_load_file(parser, fname);
690 iseq = rb_iseq_new_top(&ast->body, rb_fstring_lit(
"<top (required)>"),
691 fname, rb_realpath_internal(
Qnil, fname, 1), NULL);
696 rb_exec_event_hook_script_compiled(ec, iseq,
Qnil);
700static inline enum ruby_tag_type
703 enum ruby_tag_type state;
705 volatile VALUE wrapper = th->top_wrapper;
706 volatile VALUE self = th->top_self;
715 th->top_wrapper = load_wrapper;
719 state = EC_EXEC_TAG();
720 if (state == TAG_NONE) {
721 load_iseq_eval(ec, fname);
730 th->top_wrapper = wrapper;
738 rb_vm_jump_tag_but_local_jump(state);
741 if (!
NIL_P(ec->errinfo)) {
750 enum ruby_tag_type state = TAG_NONE;
755 state = load_wrapping(ec, fname, wrap);
758 load_iseq_eval(ec, fname);
760 raise_load_if_failed(ec, state);
767 if (!tmp) load_failed(fname);
768 rb_load_internal(tmp, RBOOL(wrap));
774 enum ruby_tag_type state;
776 EC_PUSH_TAG(GET_EC());
777 if ((state = EC_EXEC_TAG()) == TAG_NONE) {
782 if (state != TAG_NONE) *pstate = state;
819 VALUE fname, wrap, path, orig_fname;
821 rb_scan_args(argc, argv,
"11", &fname, &wrap);
823 orig_fname = rb_get_path_check_to_string(fname);
824 fname = rb_str_encode_ospath(orig_fname);
825 RUBY_DTRACE_HOOK(LOAD_ENTRY, RSTRING_PTR(orig_fname));
827 path = rb_find_file(fname);
829 if (!rb_file_load_ok(RSTRING_PTR(fname)))
830 load_failed(orig_fname);
833 rb_load_internal(path, wrap);
835 RUBY_DTRACE_HOOK(LOAD_RETURN, RSTRING_PTR(orig_fname));
841load_lock(
rb_vm_t *vm,
const char *ftptr,
bool warn)
844 st_table *loading_tbl = get_loading_table(vm);
846 if (!st_lookup(loading_tbl, (st_data_t)ftptr, &data)) {
849 data = (st_data_t)rb_thread_shield_new();
850 st_insert(loading_tbl, (st_data_t)ftptr, data);
851 return (
char *)ftptr;
854 VALUE warning = rb_warning_string(
"loading in progress, circular require considered harmful - %s", ftptr);
858 switch (rb_thread_shield_wait((
VALUE)data)) {
863 return (
char *)ftptr;
867release_thread_shield(st_data_t *key, st_data_t *value, st_data_t done,
int existing)
870 if (!existing)
return ST_STOP;
872 rb_thread_shield_destroy(thread_shield);
876 else if (rb_thread_shield_release(thread_shield)) {
885load_unlock(
rb_vm_t *vm,
const char *ftptr,
int done)
888 st_data_t key = (st_data_t)ftptr;
889 st_table *loading_tbl = get_loading_table(vm);
891 st_update(loading_tbl, key, release_thread_shield, done);
952 VALUE base = rb_current_realfilepath();
956 base = rb_file_dirname(base);
960typedef int (*feature_func)(
rb_vm_t *vm,
const char *feature,
const char *ext,
int rb,
int expanded,
const char **fn);
963search_required(
rb_vm_t *vm,
VALUE fname,
volatile VALUE *path, feature_func rb_feature_p)
971 ext = strrchr(ftptr = RSTRING_PTR(fname),
'.');
972 if (ext && !strchr(ext,
'/')) {
974 if (rb_feature_p(vm, ftptr, ext, TRUE, FALSE, &loading)) {
978 if ((tmp = rb_find_file(fname)) != 0) {
979 ext = strrchr(ftptr = RSTRING_PTR(tmp),
'.');
980 if (!rb_feature_p(vm, ftptr, ext, TRUE, TRUE, &loading) || loading)
986 else if (IS_SOEXT(ext)) {
987 if (rb_feature_p(vm, ftptr, ext, FALSE, FALSE, &loading)) {
994 if ((tmp = rb_find_file(tmp)) != 0) {
995 ext = strrchr(ftptr = RSTRING_PTR(tmp),
'.');
996 if (!rb_feature_p(vm, ftptr, ext, FALSE, TRUE, &loading) || loading)
1001 else if (IS_DLEXT(ext)) {
1002 if (rb_feature_p(vm, ftptr, ext, FALSE, FALSE, &loading)) {
1006 if ((tmp = rb_find_file(fname)) != 0) {
1007 ext = strrchr(ftptr = RSTRING_PTR(tmp),
'.');
1008 if (!rb_feature_p(vm, ftptr, ext, FALSE, TRUE, &loading) || loading)
1014 else if ((ft = rb_feature_p(vm, ftptr, 0, FALSE, FALSE, &loading)) ==
'r') {
1019 type = rb_find_file_ext(&tmp, ft ==
's' ? ruby_ext : loadable_ext);
1021 if (!ft &&
type != 1) {
1022 VALUE lookup_name = tmp;
1030 ftptr = RSTRING_PTR(lookup_name);
1031 if (st_lookup(vm->static_ext_inits, (st_data_t)ftptr, NULL)) {
1040 goto feature_present;
1041 ftptr = RSTRING_PTR(tmp);
1042 return rb_feature_p(vm, ftptr, 0, FALSE, TRUE, 0);
1046 goto feature_present;
1050 ext = strrchr(ftptr = RSTRING_PTR(tmp),
'.');
1051 if (rb_feature_p(vm, ftptr, ext, !--
type, TRUE, &loading) && !loading)
1055 return type ?
's' :
'r';
1063load_failed(
VALUE fname)
1065 rb_load_fail(fname,
"cannot load such file");
1071 rb_scope_visibility_set(METHOD_VISI_PUBLIC);
1072 return (
VALUE)dln_load(RSTRING_PTR(path));
1077run_static_ext_init(
rb_vm_t *vm,
const char *feature)
1079 st_data_t key = (st_data_t)feature;
1080 st_data_t init_func;
1081 if (st_delete(vm->static_ext_inits, &key, &init_func)) {
1082 ((void (*)(void))init_func)();
1090no_feature_p(
rb_vm_t *vm,
const char *feature,
const char *ext,
int rb,
int expanded,
const char **fn)
1097rb_resolve_feature_path(
VALUE klass,
VALUE fname)
1103 fname = rb_get_path(fname);
1104 path = rb_str_encode_ospath(fname);
1105 found = search_required(GET_VM(), path, &path, no_feature_p);
1109 sym =
ID2SYM(rb_intern(
"rb"));
1112 sym =
ID2SYM(rb_intern(
"so"));
1118 return rb_ary_new_from_args(2, sym, path);
1124 *prev = th->ext_config;
1131 th->ext_config = *prev;
1137 GET_THREAD()->ext_config.ractor_safe = flag;
1150 volatile int result = -1;
1152 volatile const struct {
1153 VALUE wrapper, self, errinfo;
1155 th->top_wrapper, th->top_self, ec->errinfo,
1157 enum ruby_tag_type state;
1158 char *
volatile ftptr = 0;
1160 volatile VALUE saved_path;
1161 volatile VALUE realpath = 0;
1162 VALUE realpaths = get_loaded_features_realpaths(th->vm);
1163 volatile bool reset_ext_config =
false;
1166 fname = rb_get_path(fname);
1167 path = rb_str_encode_ospath(fname);
1168 RUBY_DTRACE_HOOK(REQUIRE_ENTRY, RSTRING_PTR(fname));
1173 th->top_wrapper = 0;
1174 if ((state = EC_EXEC_TAG()) == TAG_NONE) {
1178 RUBY_DTRACE_HOOK(FIND_REQUIRE_ENTRY, RSTRING_PTR(fname));
1179 found = search_required(th->vm, path, &saved_path, rb_feature_p);
1180 RUBY_DTRACE_HOOK(FIND_REQUIRE_RETURN, RSTRING_PTR(fname));
1184 if (!path || !(ftptr = load_lock(th->vm, RSTRING_PTR(path), warn))) {
1188 result = TAG_RETURN;
1191 else if (found ==
's' && run_static_ext_init(th->vm, RSTRING_PTR(path))) {
1192 result = TAG_RETURN;
1195 else if (
RTEST(rb_hash_aref(realpaths,
1196 realpath = rb_realpath_internal(
Qnil, path, 1)))) {
1202 load_iseq_eval(ec, path);
1206 reset_ext_config =
true;
1207 ext_config_push(th, &prev_ext_config);
1208 handle = (long)rb_vm_call_cfunc(rb_vm_top_self(), load_ext,
1209 path, VM_BLOCK_HANDLER_NONE, path);
1210 rb_ary_push(ruby_dln_librefs,
LONG2NUM(handle));
1213 result = TAG_RETURN;
1220 th2->top_self = saved.self;
1221 th2->top_wrapper = saved.wrapper;
1222 if (reset_ext_config) ext_config_pop(th2, &prev_ext_config);
1225 if (ftptr) load_unlock(th2->vm, RSTRING_PTR(path), !state);
1228 if (state == TAG_FATAL || state == TAG_THROW) {
1229 EC_JUMP_TAG(ec, state);
1231 else if (exception) {
1234 VALUE exc = rb_vm_make_jump_tag_but_local_jump(state,
Qundef);
1235 if (!
NIL_P(exc)) ec->errinfo = exc;
1238 else if (state == TAG_RETURN) {
1245 if (!
NIL_P(ec->errinfo)) {
1246 if (!exception)
return TAG_RAISE;
1250 if (result == TAG_RETURN) {
1251 rb_provide_feature(th2->vm, path);
1252 VALUE real = realpath;
1254 rb_hash_aset(realpaths, rb_fstring(real),
Qtrue);
1257 ec->errinfo = saved.errinfo;
1259 RUBY_DTRACE_HOOK(REQUIRE_RETURN, RSTRING_PTR(fname));
1265rb_require_internal_silent(
VALUE fname)
1268 return require_internal(ec, fname, 1,
false);
1272rb_require_internal(
VALUE fname)
1279ruby_require_internal(
const char *fname,
unsigned int len)
1282 VALUE str = rb_setup_fake_str(&fake, fname,
len, 0);
1286 return result == TAG_RETURN ? 1 : result ? -1 : 0;
1295 if (result > TAG_RETURN) {
1296 EC_JUMP_TAG(ec, result);
1302 return RBOOL(result);
1313register_init_ext(st_data_t *key, st_data_t *value, st_data_t init,
int existing)
1315 const char *name = (
char *)*key;
1318 rb_warn(
"%s is already registered", name);
1321 *value = (st_data_t)init;
1327ruby_init_ext(
const char *name,
void (*init)(
void))
1330 st_table *inits_table = vm->static_ext_inits;
1332 if (feature_provided(vm, name, 0))
1334 st_update(inits_table, (st_data_t)name, register_init_ext, (st_data_t)init);
1362 rb_autoload_str(mod,
id, file);
1393rb_mod_autoload_p(
int argc,
VALUE *argv,
VALUE mod)
1395 int recur = (rb_check_arity(argc, 1, 2) == 1) ? TRUE :
RTEST(argv[1]);
1396 VALUE sym = argv[0];
1402 return rb_autoload_at_p(mod,
id, recur);
1427 return rb_mod_autoload(klass, sym, file);
1442rb_f_autoload_p(
int argc,
VALUE *argv,
VALUE obj)
1445 VALUE klass = rb_vm_cbase();
1449 return rb_mod_autoload_p(argc, argv, klass);
1456 static const char var_load_path[] =
"$:";
1457 ID id_load_path =
rb_intern2(var_load_path,
sizeof(var_load_path)-1);
1462 vm->load_path = rb_ary_new();
1463 vm->expanded_load_path = rb_ary_hidden_new(0);
1464 vm->load_path_snapshot = rb_ary_hidden_new(0);
1465 vm->load_path_check_cache = 0;
1470 vm->loaded_features = rb_ary_new();
1471 vm->loaded_features_snapshot = rb_ary_hidden_new(0);
1472 vm->loaded_features_index = st_init_numtable();
1473 vm->loaded_features_realpaths = rb_hash_new();
1484 ruby_dln_librefs = rb_ary_hidden_new(0);
1485 rb_gc_register_mark_object(ruby_dln_librefs);
#define rb_define_method(klass, mid, func, arity)
Defines klass#mid.
#define rb_define_singleton_method(klass, mid, func, arity)
Defines klass.mid.
#define rb_define_global_function(mid, func, arity)
Defines rb_mKernel #mid.
void rb_extend_object(VALUE obj, VALUE module)
Extend the object with the module.
VALUE rb_module_new(void)
Creates a new, anonymous module.
#define rb_str_new2
Old name of rb_str_new_cstr.
#define T_STRING
Old name of RUBY_T_STRING.
#define xfree
Old name of ruby_xfree.
#define Qundef
Old name of RUBY_Qundef.
#define INT2FIX
Old name of RB_INT2FIX.
#define OBJ_FROZEN
Old name of RB_OBJ_FROZEN.
#define rb_str_cat2
Old name of rb_str_cat_cstr.
#define ID2SYM
Old name of RB_ID2SYM.
#define SPECIAL_CONST_P
Old name of RB_SPECIAL_CONST_P.
#define OBJ_FREEZE
Old name of RB_OBJ_FREEZE.
#define T_FIXNUM
Old name of RUBY_T_FIXNUM.
#define T_MODULE
Old name of RUBY_T_MODULE.
#define LONG2NUM
Old name of RB_LONG2NUM.
#define Qtrue
Old name of RUBY_Qtrue.
#define Qnil
Old name of RUBY_Qnil.
#define Qfalse
Old name of RUBY_Qfalse.
#define FIX2LONG
Old name of RB_FIX2LONG.
#define NIL_P
Old name of RB_NIL_P.
#define FIXNUM_P
Old name of RB_FIXNUM_P.
void rb_raise(VALUE exc, const char *fmt,...)
Exception entry point.
void rb_exc_raise(VALUE mesg)
Raises an exception in the current thread.
void rb_set_errinfo(VALUE err)
Sets the current exception ($!) to the given value.
#define ruby_verbose
This variable controls whether the interpreter is in debug mode.
VALUE rb_eTypeError
TypeError exception.
VALUE rb_eRuntimeError
RuntimeError exception.
void rb_warn(const char *fmt,...)
Identical to rb_warning(), except it reports always regardless of runtime -W flag.
void rb_loaderror(const char *fmt,...)
Raises an instance of rb_eLoadError.
void rb_warning(const char *fmt,...)
Issues a warning.
VALUE rb_obj_hide(VALUE obj)
Make the object invisible from Ruby code.
VALUE rb_cModule
Module class.
VALUE rb_class_real(VALUE klass)
Finds a "real" class.
VALUE rb_obj_clone(VALUE obj)
Produces a shallow copy of the given object.
VALUE rb_obj_freeze(VALUE obj)
Just calls rb_obj_freeze_inline() inside.
void rb_provide(const char *feature)
Declares that the given feature is already provided by someone else.
VALUE rb_f_require(VALUE self, VALUE feature)
Identical to rb_require_string(), except it ignores the first argument for no reason.
void rb_ext_ractor_safe(bool flag)
Asserts that the extension library that calls this function is aware of Ractor.
VALUE rb_require_string(VALUE feature)
Finds and loads the given feature, if absent.
int rb_feature_provided(const char *feature, const char **loading)
Identical to rb_provided(), except it additionally returns the "canonical" name of the loaded feature...
void rb_load_protect(VALUE path, int wrap, int *state)
Identical to rb_load(), except it avoids potential global escapes.
int rb_provided(const char *feature)
Queries if the given feature has already been loaded into the execution context.
void rb_load(VALUE path, int wrap)
Loads and executes the Ruby program in the given file.
VALUE rb_str_append(VALUE dst, VALUE src)
Identical to rb_str_buf_append(), except it converts the right hand side before concatenating.
VALUE rb_str_tmp_new(long len)
Allocates a "temporary" string.
VALUE rb_str_subseq(VALUE str, long beg, long len)
Identical to rb_str_substr(), except the numbers are interpreted as byte offsets instead of character...
VALUE rb_str_dup(VALUE str)
Duplicates a string.
VALUE rb_filesystem_str_new_cstr(const char *ptr)
Identical to rb_filesystem_str_new(), except it assumes the passed pointer is a pointer to a C string...
VALUE rb_str_equal(VALUE str1, VALUE str2)
Equality of two strings.
#define rb_strlen_lit(str)
Length of a string literal.
VALUE rb_str_freeze(VALUE str)
This is the implementation of String#freeze.
#define rb_str_cat_cstr(buf, str)
Identical to rb_str_cat(), except it assumes the passed pointer is a pointer to a C string.
VALUE rb_str_resize(VALUE str, long len)
Overwrites the length of the string.
#define rb_str_new_cstr(str)
Identical to rb_str_new, except it assumes the passed pointer is a pointer to a C string.
void rb_alias_variable(ID dst, ID src)
Aliases a global variable.
ID rb_intern2(const char *name, long len)
Identical to rb_intern(), except it additionally takes the length of the string.
ID rb_check_id(volatile VALUE *namep)
Detects if the given name is already interned or not.
ID rb_to_id(VALUE str)
Identical to rb_intern(), except it takes an instance of rb_cString.
rb_gvar_setter_t rb_gvar_readonly_setter
This function just raises rb_eNameError.
char * ruby_strdup(const char *str)
This is our own version of strdup(3) that uses ruby_xmalloc() instead of system malloc (benefits our ...
#define MEMCPY(p1, p2, type, n)
Handy macro to call memcpy.
#define RB_GC_GUARD(v)
Prevents premature destruction of local objects.
#define MEMMOVE(p1, p2, type, n)
Handy macro to call memmove.
void rb_define_hooked_variable(const char *q, VALUE *w, type *e, void_type *r)
Define a function-backended global variable.
VALUE type(ANYARGS)
ANYARGS-ed function type.
void rb_define_virtual_variable(const char *q, type *w, void_type *e)
Define a function-backended global variable.
#define RARRAY_LEN
Just another name of rb_array_len.
#define RARRAY_AREF(a, i)
#define StringValue(v)
Ensures that the parameter object is a String.
#define StringValuePtr(v)
Identical to StringValue, except it returns a char*.
VALUE rb_require(const char *feature)
Identical to rb_require_string(), except it takes C's string instead of Ruby's.
#define FilePathValue(v)
Ensures that the parameter object is a path.
#define RTEST
This is an old name of RB_TEST.
#define _(args)
This was a transition path from K&R to ANSI.
long len
Length of the string, not including terminating NUL character.
uintptr_t VALUE
Type that represents a Ruby object.
uintptr_t ID
Type that represents a Ruby identifier such as a variable name.