13static VALUE ruby_dln_librefs;
15#define IS_RBEXT(e) (strcmp((e), ".rb") == 0)
16#define IS_SOEXT(e) (strcmp((e), ".so") == 0 || strcmp((e), ".o") == 0)
18#define IS_DLEXT(e) (strcmp((e), DLEXT) == 0 || strcmp((e), DLEXT2) == 0)
20#define IS_DLEXT(e) (strcmp((e), DLEXT) == 0)
23static const char *
const loadable_ext[] = {
31static const char *
const ruby_ext[] = {
49rb_construct_expanded_load_path(
enum expand_type type,
int *has_relative,
int *has_non_cache)
60 int is_string, non_cache;
64 non_cache = !is_string ? 1 : 0;
72 (!as_cstr[0] || as_cstr[0] !=
'~')) ||
81 if (!*has_non_cache && non_cache)
88 if (
NIL_P(expanded_path)) expanded_path = as_str;
104 int has_relative = 0, has_non_cache = 0;
105 rb_construct_expanded_load_path(
EXPAND_ALL, &has_relative, &has_non_cache);
109 else if (has_non_cache) {
118 int has_relative = 1, has_non_cache = 1;
121 &has_relative, &has_non_cache);
124 int has_relative = 1, has_non_cache = 1;
131 &has_relative, &has_non_cache);
136 &has_relative, &has_non_cache);
143load_path_getter(
ID id,
VALUE * p)
150get_loaded_features(
void)
152 return GET_VM()->loaded_features;
156get_LOADED_FEATURES(
ID _x,
VALUE *_y)
158 return get_loaded_features();
162reset_loaded_features_snapshot(
void)
169get_loaded_features_index_raw(
void)
171 return GET_VM()->loaded_features_index;
175get_loading_table(
void)
177 return GET_VM()->loading_table;
181feature_key(
const char *
str,
size_t len)
187is_rbext_path(
VALUE feature_path)
191 if (
len <= rbext_len)
return false;
196features_index_add_single(
const char*
str,
size_t len,
VALUE offset,
bool rb)
203 short_feature_key = feature_key(
str,
len);
205 features_index = get_loaded_features_index_raw();
208 if (
NIL_P(this_feature_index)) {
212 VALUE loaded_features = get_loaded_features();
214 VALUE feature_indexes[2];
215 int top = (rb && !is_rbext_path(this_feature_path)) ? 1 : 0;
216 feature_indexes[
top^0] = this_feature_index;
217 feature_indexes[
top^1] = offset;
228 VALUE loaded_features = get_loaded_features();
233 if (!is_rbext_path(this_feature_path)) {
261features_index_add(
VALUE feature,
VALUE offset)
263 const char *feature_str, *feature_end, *ext, *p;
269 for (ext = feature_end; ext > feature_str; ext--)
270 if (*ext ==
'.' || *ext ==
'/')
279 p = ext ? ext : feature_end;
282 while (p >= feature_str && *p !=
'/')
287 features_index_add_single(p + 1, feature_end - p - 1, offset,
false);
289 features_index_add_single(p + 1, ext - p - 1, offset, rb);
292 features_index_add_single(feature_str, feature_end - feature_str, offset,
false);
294 features_index_add_single(feature_str, ext - feature_str, offset, rb);
310get_loaded_features_index(
void)
328 features_index_add(as_str,
INT2FIX(
i));
330 reset_loaded_features_snapshot();
347loaded_feature_path(
const char *
name,
long vlen,
const char *feature,
long len,
354 if (vlen <
len+1)
return 0;
359 for (e =
name + vlen;
name != e && *e !=
'.' && *e !=
'/'; --e);
366 if (plen > 0 &&
name[plen-1] !=
'/') {
377 if (plen > 0) --plen;
383 if (
n != plen)
continue;
401 const char *s = (
const char *)
v;
411rb_feature_p(
const char *feature,
const char *ext,
int rb,
int expanded,
const char **fn)
415 long i,
len, elen,
n;
416 st_table *loading_tbl, *features_index;
425 type = rb ?
'r' :
's';
432 features = get_loaded_features();
433 features_index = get_loaded_features_index();
435 key = feature_key(feature,
strlen(feature));
463 if (!
NIL_P(this_feature_index)) {
473 entry = this_feature_index;
481 if (expanded)
continue;
488 if (!*(e =
f +
len)) {
492 if (*e !=
'.')
continue;
496 if ((rb || !ext) && (
IS_RBEXT(e))) {
502 loading_tbl = get_loading_table();
512 if ((
f = fs.result) != 0) {
518 if (fn) *fn = (
const char*)data;
520 if (!ext)
return 'u';
526 static const char so_ext[][4] = {
530 if (ext && *ext)
return 0;
534 for (
i = 0; (e = loadable_ext[
i]) != 0;
i++) {
538 if (fn) *fn = (
const char*)data;
539 return i ?
's' :
'r';
546 if (fn) *fn = (
const char*)data;
564 const char *ext =
strrchr(feature,
'.');
567 if (*feature ==
'.' &&
568 (feature[1] ==
'/' ||
strncmp(feature+1,
"./", 2) == 0)) {
572 if (ext && !
strchr(ext,
'/')) {
574 if (rb_feature_p(feature, ext,
TRUE,
FALSE, loading))
return TRUE;
578 if (rb_feature_p(feature, ext,
FALSE,
FALSE, loading))
return TRUE;
582 if (rb_feature_p(feature, 0,
TRUE,
FALSE, loading))
589rb_provide_feature(
VALUE feature)
593 features = get_loaded_features();
596 "$LOADED_FEATURES is frozen; cannot append feature");
600 get_loaded_features_index();
603 reset_loaded_features_snapshot();
628 rb_exec_event_hook_script_compiled(ec,
iseq,
Qnil);
653 load_iseq_eval(ec, fname);
679rb_load_internal(
VALUE fname,
int wrap)
684 state = load_wrapping(ec, fname);
687 load_iseq_eval(ec, fname);
689 raise_load_if_failed(ec, state);
696 if (!tmp) load_failed(fname);
697 rb_load_internal(tmp, wrap);
711 if (state !=
TAG_NONE) *pstate = state;
742 load_failed(orig_fname);
753load_lock(
const char *ftptr)
756 st_table *loading_tbl = get_loading_table();
763 return (
char *)ftptr;
774 VALUE warning =
rb_warning_string(
"loading in progress, circular require considered harmful - %s", ftptr);
783 return (
char *)ftptr;
805load_unlock(
const char *ftptr,
int done)
809 st_table *loading_tbl = get_loading_table();
811 st_update(loading_tbl,
key, release_thread_shield, done);
877typedef int (*
feature_func)(
const char *feature,
const char *ext,
int rb,
int expanded,
const char **fn);
889 if (ext && !
strchr(ext,
'/')) {
891 if (rb_feature_p(ftptr, ext,
TRUE,
FALSE, &loading)) {
897 if (!rb_feature_p(ftptr, ext,
TRUE,
TRUE, &loading) || loading)
904 if (rb_feature_p(ftptr, ext,
FALSE,
FALSE, &loading)) {
913 if (!rb_feature_p(ftptr, ext,
FALSE,
TRUE, &loading) || loading)
922 if (!rb_feature_p(ftptr, ext,
FALSE,
TRUE, &loading) || loading)
929 if (rb_feature_p(ftptr, ext,
FALSE,
FALSE, &loading)) {
935 if (!rb_feature_p(ftptr, ext,
FALSE,
TRUE, &loading) || loading)
941 else if ((ft = rb_feature_p(ftptr, 0,
FALSE,
FALSE, &loading)) ==
'r') {
950 goto statically_linked;
952 return rb_feature_p(ftptr, 0,
FALSE,
TRUE, 0);
963 if (rb_feature_p(ftptr, ext, !--
type,
TRUE, &loading) && !loading)
967 return type ?
's' :
'r';
971load_failed(
VALUE fname)
984no_feature_p(
const char *feature,
const char *ext,
int rb,
int expanded,
const char **fn)
999 found = search_required(
path, &
path, no_feature_p);
1025 volatile int result = -1;
1031 char *
volatile ftptr = 0;
1046 found = search_required(
path, &
path, rb_feature_p);
1059 load_iseq_eval(ec,
path);
1073 th = rb_ec_thread_ptr(ec);
1082 else if (exception) {
1113 return require_internal(ec, fname, 1);
1122 int result = require_internal(ec,
str, 0);
1124 return result ==
TAG_RETURN ? 1 : result ? -1 : 0;
1130 rb_warn(
"rb_require_safe will be removed in Ruby 3.0");
1132 int result = require_internal(ec, fname, 1);
1148 int result = require_internal(ec, fname, 1);
1169 const char *
name = (
char *)*
key;
1184 st_table *loading_tbl = get_loading_table();
1272 return rb_mod_autoload(
klass,
sym, file);
1301#define rb_intern(str) rb_intern2((str), strlen(str))
1303 static const char var_load_path[] =
"$:";
1304 ID id_load_path =
rb_intern2(var_load_path,
sizeof(var_load_path)-1);
void * dln_load(const char *file)
char str[HTML_ESCAPE_MAX_LEN+1]
VALUE rb_check_realpath(VALUE basedir, VALUE path, rb_encoding *enc)
void rb_extend_object(VALUE, VALUE)
Extend the object with the module.
VALUE rb_module_new(void)
VALUE rb_require(const char *fname)
VALUE rb_cModule
Module class.
void rb_raise(VALUE exc, const char *fmt,...)
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.
void rb_load_fail(VALUE path, const char *err)
void rb_warn(const char *fmt,...)
void rb_loaderror(const char *fmt,...)
VALUE rb_class_real(VALUE cl)
Looks up the nearest ancestor of cl, skipping singleton classes or module inclusions.
VALUE rb_obj_clone(VALUE)
Almost same as Object::clone.
VALUE rb_obj_freeze(VALUE)
Make the object unmodifiable.
VALUE rb_require_string(VALUE fname)
int(* feature_func)(const char *feature, const char *ext, int rb, int expanded, const char **fn)
void rb_provide(const char *feature)
void rb_load(VALUE fname, int wrap)
void rb_load_protect(VALUE fname, int wrap, int *pstate)
RUBY_FUNC_EXPORTED void ruby_init_ext(const char *name, void(*init)(void))
VALUE rb_f_require(VALUE obj, VALUE fname)
int rb_require_internal(VALUE fname)
VALUE rb_f_require_relative(VALUE obj, VALUE fname)
int rb_feature_provided(const char *feature, const char **loading)
VALUE rb_resolve_feature_path(VALUE klass, VALUE fname)
VALUE rb_require_safe(VALUE fname, int safe)
NORETURN(static void load_failed(VALUE))
int rb_provided(const char *feature)
int ruby_require_internal(const char *fname, unsigned int len)
VALUE rb_get_expanded_load_path(void)
VALUE type(ANYARGS)
ANYARGS-ed function type.
st_table * st_init_numtable(void)
int st_insert(st_table *tab, st_data_t key, st_data_t value)
st_index_t st_hash(const void *ptr, size_t len, st_index_t h)
int st_lookup(st_table *tab, st_data_t key, st_data_t *value)
int st_foreach(st_table *tab, st_foreach_callback_func *func, st_data_t arg)
int st_update(st_table *tab, st_data_t key, st_update_callback_func *func, st_data_t arg)
int st_get_key(st_table *tab, st_data_t key, st_data_t *result)
VALUE rb_setup_fake_str(struct RString *fake_str, const char *name, long len, rb_encoding *enc)
VALUE load_path_check_cache
struct st_table * loaded_features_index
VALUE loaded_features_snapshot
char * ruby_strdup(const char *)
void rb_vm_jump_tag_but_local_jump(int state)
VALUE rb_vm_top_self(void)