11 static VALUE ruby_dln_librefs;
13 #define IS_RBEXT(e) (strcmp((e), ".rb") == 0) 14 #define IS_SOEXT(e) (strcmp((e), ".so") == 0 || strcmp((e), ".o") == 0) 16 #define IS_DLEXT(e) (strcmp((e), DLEXT) == 0 || strcmp((e), DLEXT2) == 0) 18 #define IS_DLEXT(e) (strcmp((e), DLEXT) == 0) 21 static const char *
const loadable_ext[] = {
49 rb_construct_expanded_load_path(
enum expand_type type,
int *has_relative,
int *has_non_cache)
60 VALUE path, as_str, expanded_path;
61 int is_string, non_cache;
65 non_cache = !is_string ? 1 : 0;
73 (!as_cstr[0] || as_cstr[0] !=
'~')) ||
82 if (!*has_non_cache && non_cache)
89 if (
NIL_P(expanded_path)) expanded_path = as_str;
98 load_path_getcwd(
void)
114 int has_relative = 0, has_non_cache = 0;
115 rb_construct_expanded_load_path(
EXPAND_ALL, &has_relative, &has_non_cache);
119 else if (has_non_cache) {
128 int has_relative = 1, has_non_cache = 1;
131 &has_relative, &has_non_cache);
134 int has_relative = 1, has_non_cache = 1;
135 VALUE cwd = load_path_getcwd();
141 &has_relative, &has_non_cache);
146 &has_relative, &has_non_cache);
159 get_loaded_features(
void)
161 return GET_VM()->loaded_features;
165 reset_loaded_features_snapshot(
void)
172 get_loaded_features_index_raw(
void)
174 return GET_VM()->loaded_features_index;
178 get_loading_table(
void)
180 return GET_VM()->loading_table;
184 features_index_add_single(
VALUE short_feature,
VALUE offset)
188 char *short_feature_cstr;
194 features_index = get_loaded_features_index_raw();
197 if (
NIL_P(this_feature_index)) {
201 VALUE feature_indexes[2];
202 feature_indexes[0] = this_feature_index;
203 feature_indexes[1] = offset;
224 features_index_add(
VALUE feature,
VALUE offset)
227 const char *feature_str, *feature_end, *ext, *p;
232 for (ext = feature_end; ext > feature_str; ext--)
233 if (*ext ==
'.' || *ext ==
'/')
240 p = ext ? ext : feature_end;
245 while (p >= feature_str && *p !=
'/')
250 beg = p + 1 - feature_str;
251 short_feature =
rb_str_subseq(feature, beg, feature_end - p - 1);
252 features_index_add_single(short_feature, offset);
255 features_index_add_single(short_feature, offset);
258 features_index_add_single(feature, offset);
260 short_feature =
rb_str_subseq(feature, 0, ext - feature_str);
261 features_index_add_single(short_feature, offset);
278 get_loaded_features_index(
void)
296 features_index_add(as_str,
INT2FIX(i));
298 reset_loaded_features_snapshot();
315 loaded_feature_path(
const char *
name,
long vlen,
const char *feature,
long len,
322 if (vlen <
len+1)
return 0;
327 for (e =
name + vlen;
name != e && *e !=
'.' && *e !=
'/'; --e);
330 strncmp(e-
len, feature,
len))
334 if (plen > 0 &&
name[plen-1] !=
'/') {
345 if (plen > 0) --plen;
351 if (n != plen)
continue;
352 if (n && strncmp(
name, s, n))
continue;
369 const char *s = (
const char *)v;
379 rb_feature_p(
const char *feature,
const char *ext,
int rb,
int expanded,
const char **fn)
383 long i,
len, elen, n;
384 st_table *loading_tbl, *features_index;
391 len =
strlen(feature) - elen;
392 type = rb ?
'r' :
's';
399 features = get_loaded_features();
400 features_index = get_loaded_features_index();
429 if (!
NIL_P(this_feature_index)) {
434 if (i >=
RARRAY_LEN(this_feature_index))
break;
439 entry = this_feature_index;
446 if (strncmp(f, feature, len) != 0) {
447 if (expanded)
continue;
449 if (!(p = loaded_feature_path(f, n, feature, len, type, load_path)))
454 if (!*(e = f + len)) {
458 if (*e !=
'.')
continue;
462 if ((rb || !ext) && (
IS_RBEXT(e))) {
468 loading_tbl = get_loading_table();
478 if ((f = fs.result) != 0) {
484 if (fn) *fn = (
const char*)data;
486 if (!ext)
return 'u';
492 static const char so_ext[][4] = {
496 if (ext && *ext)
return 0;
499 MEMCPY(buf, feature,
char, len);
500 for (i = 0; (e = loadable_ext[i]) != 0; i++) {
504 if (fn) *fn = (
const char*)data;
505 return i ?
's' :
'r';
508 for (i = 0; i <
numberof(so_ext); i++) {
512 if (fn) *fn = (
const char*)data;
530 const char *ext =
strrchr(feature,
'.');
533 if (*feature ==
'.' &&
534 (feature[1] ==
'/' || strncmp(feature+1,
"./", 2) == 0)) {
538 if (ext && !
strchr(ext,
'/')) {
540 if (rb_feature_p(feature, ext,
TRUE,
FALSE, loading))
return TRUE;
544 if (rb_feature_p(feature, ext,
FALSE,
FALSE, loading))
return TRUE;
548 if (rb_feature_p(feature, 0,
TRUE,
FALSE, loading))
555 rb_provide_feature(
VALUE feature)
559 features = get_loaded_features();
562 "$LOADED_FEATURES is frozen; cannot append feature");
568 reset_loaded_features_snapshot();
586 #if !defined __GNUC__ 622 #if !defined __GNUC__ 633 if (
NIL_P(exc))
return state;
646 rb_load_internal(
VALUE fname,
int wrap)
649 int state = rb_load_internal0(curr_th, fname, wrap);
657 file_to_load(
VALUE fname)
660 if (!tmp) load_failed(fname);
667 rb_load_internal(file_to_load(fname), wrap);
674 volatile VALUE path = 0;
678 path = file_to_load(fname);
683 if (state !=
TAG_NONE) *pstate = state;
703 VALUE fname, wrap, path, orig_fname;
714 load_failed(orig_fname);
717 rb_load_internal(path,
RTEST(wrap));
727 load_lock(
const char *ftptr)
730 st_table *loading_tbl = get_loading_table();
737 return (
char *)ftptr;
741 void (*init)(void) = (
void (*)(void))memo->
u3.
func;
748 VALUE warning =
rb_warning_string(
"loading in progress, circular require considered harmful - %s", ftptr);
757 return (
char *)ftptr;
779 load_unlock(
const char *ftptr,
int done)
783 st_table *loading_tbl = get_loading_table();
785 st_update(loading_tbl, key, release_thread_shield, done);
852 search_required(
VALUE fname,
volatile VALUE *path,
int safe_level)
861 if (ext && !
strchr(ext,
'/')) {
863 if (rb_feature_p(ftptr, ext,
TRUE,
FALSE, &loading)) {
869 if (!rb_feature_p(ftptr, ext,
TRUE,
TRUE, &loading) || loading)
876 if (rb_feature_p(ftptr, ext,
FALSE,
FALSE, &loading)) {
885 if (!rb_feature_p(ftptr, ext,
FALSE,
TRUE, &loading) || loading)
894 if (!rb_feature_p(ftptr, ext,
FALSE,
TRUE, &loading) || loading)
901 if (rb_feature_p(ftptr, ext,
FALSE,
FALSE, &loading)) {
907 if (!rb_feature_p(ftptr, ext,
FALSE,
TRUE, &loading) || loading)
913 else if ((ft = rb_feature_p(ftptr, 0,
FALSE,
FALSE, &loading)) ==
'r') {
922 goto statically_linked;
924 return rb_feature_p(ftptr, 0,
FALSE,
TRUE, 0);
934 if (rb_feature_p(ftptr, ext, !--type,
TRUE, &loading) && !loading)
938 return type ?
's' :
'r';
942 load_failed(
VALUE fname)
971 char *
volatile ftptr = 0;
987 found = search_required(path, &path, safe);
991 if (!path || !(ftptr = load_lock(
RSTRING_PTR(path)))) {
995 rb_provide_feature(path);
1001 state = rb_load_internal0(th, path, 0);
1011 rb_provide_feature(path);
1018 load_unlock(ftptr, !state);
1041 return result ==
TAG_RETURN ? 1 : result ? -1 : 0;
1070 const char *
name = (
char *)*
key;
1073 rb_warn(
"%s is already registered", name);
1085 st_table *loading_tbl = get_loading_table();
1157 return rb_mod_autoload(klass, sym, file);
1179 return rb_mod_autoload_p(klass, sym);
1186 #define rb_intern(str) rb_intern2((str), strlen(str)) 1188 static const char var_load_path[] =
"$:";
1189 ID id_load_path =
rb_intern2(var_load_path,
sizeof(var_load_path)-1);
1197 vm->load_path_check_cache = 0;
VALUE rb_get_path_check_convert(VALUE obj, VALUE tmp, int level)
ID rb_check_id(volatile VALUE *)
Returns ID for the given name if it is interned already, or 0.
VALUE rb_get_path(VALUE obj)
void rb_warn(const char *fmt,...)
VALUE rb_ary_entry(VALUE ary, long offset)
VALUE rb_str_equal(VALUE str1, VALUE str2)
size_t strlen(const char *)
void rb_load_protect(VALUE fname, int wrap, int *pstate)
void rb_define_virtual_variable(const char *, VALUE(*)(ANYARGS), void(*)(ANYARGS))
ID rb_intern2(const char *, long)
int rb_is_absolute_path(const char *path)
NORETURN(static void load_failed(VALUE))
VALUE rb_setup_fake_str(struct RString *fake_str, const char *name, long len, rb_encoding *enc)
VALUE rb_fstring_cstr(const char *str)
void rb_raise(VALUE exc, const char *fmt,...)
VALUE rb_current_realfilepath(void)
struct st_table * loaded_features_index
int rb_provided(const char *feature)
VALUE rb_vm_call_cfunc(VALUE recv, VALUE(*func)(VALUE), VALUE arg, VALUE block_handler, VALUE filename)
VALUE rb_get_path_check_to_string(VALUE obj, int level)
int ruby_require_internal(const char *fname, unsigned int len)
#define TH_JUMP_TAG(th, st)
VALUE rb_ary_push(VALUE ary, VALUE item)
#define VM_BLOCK_HANDLER_NONE
void rb_backtrace_each(VALUE(*iter)(VALUE recv, VALUE str), VALUE output)
VALUE rb_ary_tmp_new(long capa)
VALUE rb_ary_shared_with_p(VALUE ary1, VALUE ary2)
int st_get_key(st_table *, st_data_t, st_data_t *)
int rb_require_internal(VALUE fname, int safe)
VALUE rb_f_require_relative(VALUE obj, VALUE fname)
RUBY_FUNC_EXPORTED void ruby_init_ext(const char *name, void(*init)(void))
VALUE rb_get_load_path(void)
int st_update(st_table *table, st_data_t key, st_update_callback_func *func, st_data_t arg)
void rb_define_global_function(const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a global function.
#define RUBY_DTRACE_HOOK(name, arg)
#define MEMO_NEW(a, b, c)
VALUE rb_str_tmp_new(long)
VALUE rb_ary_cat(VALUE ary, const VALUE *argv, long len)
void rb_load_fail(VALUE path, const char *err)
const rb_iseq_t * rb_iseq_load_iseq(VALUE fname)
VALUE rb_f_require(VALUE obj, VALUE fname)
RUBY_SYMBOL_EXPORT_BEGIN typedef unsigned long st_data_t
VALUE rb_warning_warn(VALUE mod, VALUE str)
#define RB_TYPE_P(obj, type)
void * rb_parser_load_file(VALUE parser, VALUE name)
void rb_ary_free(VALUE ary)
VALUE rb_find_file(VALUE path)
VALUE rb_str_encode_ospath(VALUE path)
char * ruby_strdup(const char *)
VALUE rb_require(const char *fname)
VALUE rb_ary_replace(VALUE copy, VALUE orig)
VALUE rb_str_cat2(VALUE, const char *)
void rb_set_errinfo(VALUE err)
Sets the current exception ($!) to the given value.
VALUE rb_thread_shield_release(VALUE self)
rb_iseq_t * rb_iseq_new_top(NODE *node, VALUE name, VALUE path, VALUE realpath, const rb_iseq_t *parent)
VALUE load_path_check_cache
void rb_ary_store(VALUE ary, long idx, VALUE val)
VALUE rb_parser_set_context(VALUE vparser, const struct rb_block *base, int main)
RUBY_EXTERN VALUE rb_cModule
void rb_gc_register_mark_object(VALUE obj)
#define RUBY_FUNC_EXPORTED
#define MEMCPY(p1, p2, type, n)
void rb_provide(const char *feature)
VALUE rb_find_file_safe(VALUE path, int safe_level)
VALUE rb_file_absolute_path(VALUE fname, VALUE dname)
VALUE rb_str_resize(VALUE, long)
VALUE rb_str_subseq(VALUE, long, long)
void rb_alias_variable(ID, ID)
VALUE rb_obj_freeze(VALUE)
call-seq: obj.freeze -> obj
void rb_gvar_readonly_setter(VALUE v, ID id, void *d, struct rb_global_variable *g)
VALUE rb_file_dirname(VALUE fname)
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
VALUE rb_thread_shield_destroy(VALUE self)
unsigned char buf[MIME_BUF_SIZE]
void rb_load(VALUE fname, int wrap)
void rb_exc_raise(VALUE mesg)
Raises an exception in the current thread.
VALUE rb_check_realpath(VALUE basedir, VALUE path)
VALUE rb_vm_top_self(void)
char * strchr(char *, char)
RUBY_EXTERN size_t strlcpy(char *, const char *, size_t)
VALUE rb_str_new_cstr(const char *)
void * dln_load(const char *file)
void rb_define_hooked_variable(const char *, VALUE *, VALUE(*)(ANYARGS), void(*)(ANYARGS))
register unsigned int len
VALUE rb_str_freeze(VALUE)
#define StringValueCStr(v)
void rb_set_safe_level_force(int)
VALUE rb_thread_shield_new(void)
VALUE rb_module_new(void)
#define RARRAY_AREF(a, i)
void rb_extend_object(VALUE obj, VALUE module)
Extend the object with the module.
VALUE rb_warning_string(const char *fmt,...)
VALUE rb_iseq_eval(const rb_iseq_t *iseq)
void rb_scope_visibility_set(rb_method_visibility_t)
VALUE rb_errinfo(void)
The current exception in the current thread.
const struct st_hash_type * type
VALUE loaded_features_snapshot
VALUE rb_filesystem_str_new_cstr(const char *)
VALUE rb_parser_new(void)
VALUE rb_thread_shield_wait(VALUE self)
VALUE rb_realpath_internal(VALUE basedir, VALUE path, int strict)
rb_execution_context_t ec
int rb_feature_provided(const char *feature, const char **loading)
int rb_find_file_ext_safe(VALUE *filep, const char *const *ext, int safe_level)
int rb_file_load_ok(const char *path)
void rb_autoload_str(VALUE mod, ID id, VALUE file)
#define StringValuePtr(v)
VALUE rb_get_expanded_load_path(void)
#define SPECIAL_CONST_P(x)
VALUE rb_vm_make_jump_tag_but_local_jump(int state, VALUE val)
VALUE rb_get_path_check(VALUE obj, int level)
VALUE rb_class_real(VALUE cl)
Looks up the nearest ancestor of cl, skipping singleton classes or module inclusions.
VALUE rb_obj_clone(VALUE)
:nodoc Almost same as Object::clone ++
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
VALUE rb_str_append(VALUE, VALUE)
void rb_loaderror(const char *fmt,...)
VALUE rb_require_safe(VALUE fname, int safe)
char * strrchr(const char *, const char)
VALUE rb_file_expand_path_fast(VALUE fname, VALUE dname)
VALUE rb_autoload_p(VALUE, ID)