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"
20static 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)
26static const char *
const loadable_ext[] = {
31static const char *
const ruby_ext[] = {
49rb_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;
58 VALUE path, as_str, expanded_path;
59 int is_string, non_cache;
63 non_cache = !is_string ? 1 : 0;
64 as_str = rb_get_path_check_to_string(path);
68 if ((
type == EXPAND_RELATIVE &&
70 (
type == EXPAND_HOME &&
71 (!as_cstr[0] || as_cstr[0] !=
'~')) ||
72 (
type == EXPAND_NON_CACHE)) {
80 if (!*has_non_cache && non_cache)
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;
91 vm->expanded_load_path = ary;
96get_expanded_load_path(
rb_vm_t *vm)
98 const VALUE non_cache =
Qtrue;
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) {
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;
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();
127 vm->load_path_check_cache = cwd;
128 rb_construct_expanded_load_path(vm, EXPAND_RELATIVE,
129 &has_relative, &has_non_cache);
133 rb_construct_expanded_load_path(vm, EXPAND_HOME,
134 &has_relative, &has_non_cache);
137 return vm->expanded_load_path;
141rb_get_expanded_load_path(
void)
143 return get_expanded_load_path(GET_VM());
147load_path_getter(ID
id, VALUE * p)
150 return vm->load_path;
154get_loaded_features(
rb_vm_t *vm)
156 return vm->loaded_features;
160get_loaded_features_realpaths(
rb_vm_t *vm)
162 return vm->loaded_features_realpaths;
166get_LOADED_FEATURES(ID _x, VALUE *_y)
168 return get_loaded_features(GET_VM());
172reset_loaded_features_snapshot(
rb_vm_t *vm)
174 rb_ary_replace(vm->loaded_features_snapshot, vm->loaded_features);
178get_loaded_features_index_raw(
rb_vm_t *vm)
180 return vm->loaded_features_index;
186 return vm->loading_table;
190feature_key(
const char *str,
size_t len)
192 return st_hash(str, len, 0xfea7009e);
196is_rbext_path(VALUE feature_path)
200 if (len <= rbext_len)
return false;
201 return IS_RBEXT(
RSTRING_PTR(feature_path) + len - rbext_len);
205features_index_add_single(
rb_vm_t *vm,
const char* str,
size_t len, VALUE offset,
bool rb)
208 VALUE this_feature_index =
Qnil;
209 st_data_t short_feature_key;
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);
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;
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);
237 VALUE loaded_features = get_loaded_features(vm);
238 for (
long i = 0; i <
RARRAY_LEN(this_feature_index); ++i) {
242 if (!is_rbext_path(this_feature_path)) {
255 MEMMOVE(ptr + pos, ptr + pos + 1, VALUE, len - pos - 1);
270features_index_add(
rb_vm_t *vm, VALUE feature, VALUE offset)
272 const char *feature_str, *feature_end, *ext, *p;
278 for (ext = feature_end; ext > feature_str; ext--)
279 if (*ext ==
'.' || *ext ==
'/')
288 p = ext ? ext : feature_end;
291 while (p >= feature_str && *p !=
'/')
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);
308loaded_features_index_clear_i(st_data_t key, st_data_t val, st_data_t arg)
310 VALUE obj = (
VALUE)val;
313 ruby_sized_xfree((
void *)obj,
sizeof(
struct RArray));
319get_loaded_features_index(
rb_vm_t *vm)
327 st_foreach(vm->loaded_features_index, loaded_features_index_clear_i, 0);
329 VALUE realpaths = vm->loaded_features_realpaths;
331 features = vm->loaded_features;
339 features_index_add(vm, as_str,
INT2FIX(i));
341 reset_loaded_features_snapshot(vm);
343 features =
rb_ary_dup(vm->loaded_features_snapshot);
345 for (i = 0; i < j; i++) {
347 VALUE realpath = rb_check_realpath(
Qnil, as_str, NULL);
348 if (
NIL_P(realpath)) realpath = as_str;
352 return vm->loaded_features_index;
367loaded_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]) :
397 if (plen > 0) --plen;
403 if (n != plen)
continue;
404 if (n && strncmp(name, s, n))
continue;
419loaded_feature_path_i(st_data_t v, st_data_t b, st_data_t f)
421 const char *s = (
const char *)v;
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;
431rb_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));
482 if (st_lookup(features_index, key, &data) && !
NIL_P(this_feature_index = (VALUE)data)) {
487 if (i >=
RARRAY_LEN(this_feature_index))
break;
492 entry = this_feature_index;
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)))
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);
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;
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)) {
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)) {
563 if (fn) *fn = (
const char*)data;
572 if (!ext)
return 'u';
573 return !IS_RBEXT(ext) ?
's' :
'r';
583feature_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)) {
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))
612 return feature_provided(GET_VM(), feature, loading);
616rb_provide_feature(
rb_vm_t *vm, VALUE feature)
620 features = get_loaded_features(vm);
623 "$LOADED_FEATURES is frozen; cannot append feature");
627 get_loaded_features_index(vm);
634 reset_loaded_features_snapshot(vm);
640 rb_provide_feature(GET_VM(), rb_fstring_cstr(feature));
643NORETURN(
static void load_failed(VALUE));
648 const rb_iseq_t *iseq = rb_iseq_load_iseq(fname);
652 VALUE parser = rb_parser_new();
653 rb_parser_set_context(parser, NULL, FALSE);
654 ast = (
rb_ast_t *)rb_parser_load_file(parser, fname);
655 iseq = rb_iseq_new_top(&ast->body, rb_fstring_lit(
"<top (required)>"),
656 fname, rb_realpath_internal(
Qnil, fname, 1), NULL);
659 rb_exec_event_hook_script_compiled(ec, iseq,
Qnil);
663static inline enum ruby_tag_type
666 enum ruby_tag_type state;
668 volatile VALUE wrapper = th->top_wrapper;
669 volatile VALUE
self = th->top_self;
677 th->top_self = rb_obj_clone(rb_vm_top_self());
678 th->top_wrapper = load_wrapper;
682 state = EC_EXEC_TAG();
683 if (state == TAG_NONE) {
684 load_iseq_eval(ec, fname);
693 th->top_wrapper = wrapper;
701 rb_vm_jump_tag_but_local_jump(state);
704 if (!
NIL_P(ec->errinfo)) {
710rb_load_internal(VALUE fname, VALUE wrap)
713 enum ruby_tag_type state = TAG_NONE;
716 wrap = rb_module_new();
718 state = load_wrapping(ec, fname, wrap);
721 load_iseq_eval(ec, fname);
723 raise_load_if_failed(ec, state);
730 if (!tmp) load_failed(fname);
731 rb_load_internal(tmp, RBOOL(wrap));
737 enum ruby_tag_type state;
739 EC_PUSH_TAG(GET_EC());
740 if ((state = EC_EXEC_TAG()) == TAG_NONE) {
745 if (state != TAG_NONE) *pstate = state;
780rb_f_load(
int argc, VALUE *argv, VALUE
_)
782 VALUE fname, wrap, path, orig_fname;
786 orig_fname = rb_get_path_check_to_string(fname);
788 RUBY_DTRACE_HOOK(LOAD_ENTRY,
RSTRING_PTR(orig_fname));
793 load_failed(orig_fname);
796 rb_load_internal(path, wrap);
798 RUBY_DTRACE_HOOK(LOAD_RETURN,
RSTRING_PTR(orig_fname));
804load_lock(
rb_vm_t *vm,
const char *ftptr,
bool warn)
807 st_table *loading_tbl = get_loading_table(vm);
809 if (!st_lookup(loading_tbl, (st_data_t)ftptr, &data)) {
812 data = (st_data_t)rb_thread_shield_new();
813 st_insert(loading_tbl, (st_data_t)ftptr, data);
814 return (
char *)ftptr;
816 else if (imemo_type_p(data, imemo_memo)) {
817 struct MEMO *memo = MEMO_CAST(data);
818 void (*init)(void) = memo->u3.func;
819 data = (st_data_t)rb_thread_shield_new();
820 st_insert(loading_tbl, (st_data_t)ftptr, data);
825 VALUE warning = rb_warning_string(
"loading in progress, circular require considered harmful - %s", ftptr);
829 switch (rb_thread_shield_wait((VALUE)data)) {
834 return (
char *)ftptr;
838release_thread_shield(st_data_t *key, st_data_t *value, st_data_t done,
int existing)
840 VALUE thread_shield = (
VALUE)*value;
841 if (!existing)
return ST_STOP;
843 rb_thread_shield_destroy(thread_shield);
847 else if (rb_thread_shield_release(thread_shield)) {
856load_unlock(
rb_vm_t *vm,
const char *ftptr,
int done)
859 st_data_t key = (st_data_t)ftptr;
860 st_table *loading_tbl = get_loading_table(vm);
862 st_update(loading_tbl, key, release_thread_shield, done);
920rb_f_require_relative(VALUE obj, VALUE fname)
922 VALUE base = rb_current_realfilepath();
924 rb_loaderror(
"cannot infer basepath");
930typedef int (*feature_func)(
rb_vm_t *vm,
const char *feature,
const char *ext,
int rb,
int expanded,
const char **fn);
933search_required(
rb_vm_t *vm, VALUE fname,
volatile VALUE *path, feature_func rb_feature_p)
942 if (ext && !strchr(ext,
'/')) {
944 if (rb_feature_p(vm, ftptr, ext, TRUE, FALSE, &loading)) {
950 if (!rb_feature_p(vm, ftptr, ext, TRUE, TRUE, &loading) || loading)
956 else if (IS_SOEXT(ext)) {
957 if (rb_feature_p(vm, ftptr, ext, FALSE, FALSE, &loading)) {
966 if (!rb_feature_p(vm, ftptr, ext, FALSE, TRUE, &loading) || loading)
971 else if (IS_DLEXT(ext)) {
972 if (rb_feature_p(vm, ftptr, ext, FALSE, FALSE, &loading)) {
978 if (!rb_feature_p(vm, ftptr, ext, FALSE, TRUE, &loading) || loading)
984 else if ((ft = rb_feature_p(vm, ftptr, 0, FALSE, FALSE, &loading)) ==
'r') {
993 goto statically_linked;
995 return rb_feature_p(vm, ftptr, 0, FALSE, TRUE, 0);
999 goto statically_linked;
1004 if (rb_feature_p(vm, ftptr, ext, !--
type, TRUE, &loading) && !loading)
1008 return type ?
's' :
'r';
1016load_failed(VALUE fname)
1018 rb_load_fail(fname,
"cannot load such file");
1024 rb_scope_visibility_set(METHOD_VISI_PUBLIC);
1029no_feature_p(
rb_vm_t *vm,
const char *feature,
const char *ext,
int rb,
int expanded,
const char **fn)
1036rb_resolve_feature_path(VALUE klass, VALUE fname)
1044 found = search_required(GET_VM(), path, &path, no_feature_p);
1063 *prev = th->ext_config;
1070 th->ext_config = *prev;
1076 GET_THREAD()->ext_config.ractor_safe = flag;
1089 volatile int result = -1;
1091 volatile const struct {
1092 VALUE wrapper,
self, errinfo;
1094 th->top_wrapper, th->top_self, ec->errinfo,
1096 enum ruby_tag_type state;
1097 char *
volatile ftptr = 0;
1099 volatile VALUE saved_path;
1100 volatile VALUE realpath = 0;
1101 VALUE realpaths = get_loaded_features_realpaths(th->vm);
1102 volatile bool reset_ext_config =
false;
1107 RUBY_DTRACE_HOOK(REQUIRE_ENTRY,
RSTRING_PTR(fname));
1112 th->top_wrapper = 0;
1113 if ((state = EC_EXEC_TAG()) == TAG_NONE) {
1117 RUBY_DTRACE_HOOK(FIND_REQUIRE_ENTRY,
RSTRING_PTR(fname));
1118 found = search_required(th->vm, path, &saved_path, rb_feature_p);
1119 RUBY_DTRACE_HOOK(FIND_REQUIRE_RETURN,
RSTRING_PTR(fname));
1123 if (!path || !(ftptr = load_lock(th->vm,
RSTRING_PTR(path), warn))) {
1127 result = TAG_RETURN;
1130 realpath = rb_realpath_internal(
Qnil, path, 1)))) {
1136 load_iseq_eval(ec, path);
1140 reset_ext_config =
true;
1141 ext_config_push(th, &prev_ext_config);
1142 handle = (long)rb_vm_call_cfunc(rb_vm_top_self(), load_ext,
1143 path, VM_BLOCK_HANDLER_NONE, path);
1147 result = TAG_RETURN;
1154 th2->top_self = saved.self;
1155 th2->top_wrapper = saved.wrapper;
1156 if (reset_ext_config) ext_config_pop(th2, &prev_ext_config);
1159 if (ftptr) load_unlock(th2->vm,
RSTRING_PTR(path), !state);
1162 if (state == TAG_FATAL || state == TAG_THROW) {
1163 EC_JUMP_TAG(ec, state);
1165 else if (exception) {
1168 VALUE exc = rb_vm_make_jump_tag_but_local_jump(state,
Qundef);
1169 if (!
NIL_P(exc)) ec->errinfo = exc;
1172 else if (state == TAG_RETURN) {
1179 if (!
NIL_P(ec->errinfo)) {
1180 if (!exception)
return TAG_RAISE;
1184 if (result == TAG_RETURN) {
1185 rb_provide_feature(th2->vm, path);
1186 VALUE real = realpath;
1191 ec->errinfo = saved.errinfo;
1193 RUBY_DTRACE_HOOK(REQUIRE_RETURN,
RSTRING_PTR(fname));
1199rb_require_internal_silent(VALUE fname)
1202 return require_internal(ec, fname, 1,
false);
1206rb_require_internal(VALUE fname)
1213ruby_require_internal(
const char *fname,
unsigned int len)
1216 VALUE str = rb_setup_fake_str(&fake, fname,
len, 0);
1220 return result == TAG_RETURN ? 1 : result ? -1 : 0;
1229 if (result > TAG_RETURN) {
1230 EC_JUMP_TAG(ec, result);
1236 return RBOOL(result);
1246register_init_ext(st_data_t *key, st_data_t *value, st_data_t init,
int existing)
1248 const char *name = (
char *)*key;
1251 rb_warn(
"%s is already registered", name);
1254 *value = (st_data_t)MEMO_NEW(0, 0, init);
1260RUBY_FUNC_EXPORTED
void
1261ruby_init_ext(
const char *name,
void (*init)(
void))
1264 st_table *loading_tbl = get_loading_table(vm);
1266 if (feature_provided(vm, name, 0))
1268 st_update(loading_tbl, (st_data_t)name, register_init_ext, (st_data_t)init);
1286rb_mod_autoload(VALUE mod, VALUE sym, VALUE file)
1291 rb_autoload_str(mod,
id, file);
1322rb_mod_autoload_p(
int argc, VALUE *argv, VALUE mod)
1325 VALUE sym = argv[0];
1331 return rb_autoload_at_p(mod,
id, recur);
1346rb_f_autoload(VALUE obj, VALUE sym, VALUE file)
1350 rb_raise(rb_eTypeError,
"Can not set autoload on singleton class");
1352 return rb_mod_autoload(klass, sym, file);
1367rb_f_autoload_p(
int argc, VALUE *argv, VALUE obj)
1370 VALUE klass = rb_vm_cbase();
1374 return rb_mod_autoload_p(argc, argv, klass);
1381 static const char var_load_path[] =
"$:";
1382 ID id_load_path =
rb_intern2(var_load_path,
sizeof(var_load_path)-1);
1390 vm->load_path_check_cache = 0;
1397 vm->loaded_features_index = st_init_numtable();
1399 rb_obj_hide(vm->loaded_features_realpaths);
#define rb_define_singleton_method(klass, mid, func, arity)
Defines klass.mid.
void rb_extend_object(VALUE obj, VALUE module)
Extend the object with the module.
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
Retrieves argument from argc and argv to given VALUE references according to the format string.
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a method.
void rb_define_global_function(const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a global function.
#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 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 T_ARRAY
Old name of RUBY_T_ARRAY.
#define NIL_P
Old name of RB_NIL_P.
#define xcalloc
Old name of ruby_xcalloc.
#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.
void rb_warn(const char *fmt,...)
Identical to rb_warning(), except it reports always regardless of runtime -W flag.
void rb_warning(const char *fmt,...)
Issues a warning.
VALUE rb_class_real(VALUE klass)
Finds a "real" class.
void rb_gc_register_mark_object(VALUE object)
Inform the garbage collector that object is a live Ruby object that should not be moved.
VALUE rb_ary_shared_with_p(VALUE lhs, VALUE rhs)
Queries if the passed two arrays share the same backend storage.
VALUE rb_ary_dup(VALUE ary)
Duplicates an array.
void rb_ary_free(VALUE ary)
Destroys the given array for no reason.
VALUE rb_ary_cat(VALUE ary, const VALUE *train, long len)
Destructively appends multiple elements at the end of the array.
VALUE rb_ary_replace(VALUE copy, VALUE orig)
Replaces the contents of the former object with the contents of the latter.
VALUE rb_ary_new(void)
Allocates a new, empty array.
VALUE rb_ary_tmp_new(long capa)
Allocates a "temporary" array.
VALUE rb_ary_clear(VALUE ary)
Destructively removes everything form an array.
VALUE rb_ary_push(VALUE ary, VALUE elem)
Special case of rb_ary_cat() that it adds only one element.
VALUE rb_ary_new_from_args(long n,...)
Constructs an array from the passed objects.
VALUE rb_ary_entry(VALUE ary, long off)
Queries an element of an array.
void rb_ary_store(VALUE ary, long key, VALUE val)
Destructively stores the passed value to the passed array's passed index.
static int rb_check_arity(int argc, int min, int max)
Ensures that the passed integer is in the passed range.
VALUE rb_find_file(VALUE path)
Identical to rb_find_file_ext(), except it takes a feature name and is extension at once,...
VALUE rb_str_encode_ospath(VALUE path)
Converts a string into an "OS Path" encoding, if any.
int rb_is_absolute_path(const char *path)
Queries if the given path is an absolute path.
int rb_find_file_ext(VALUE *feature, const char *const *exts)
Resolves a feature's path.
VALUE rb_file_dirname(VALUE fname)
Strips a file path's last component (and trailing separators if any).
VALUE rb_file_absolute_path(VALUE fname, VALUE dname)
Maps a relative path to its absolute representation.
VALUE rb_hash_aref(VALUE hash, VALUE key)
Queries the given key in the given hash table.
VALUE rb_hash_aset(VALUE hash, VALUE key, VALUE val)
Inserts or replaces ("upsert"s) the objects into the given hash table.
VALUE rb_hash_clear(VALUE hash)
Swipes everything out of the passed hash table.
VALUE rb_hash_new(void)
Creates a new, empty hash object.
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_cat2(VALUE, const char *)
Just another name of rb_str_cat_cstr.
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.
VALUE rb_str_new_cstr(const char *ptr)
Identical to rb_str_new(), 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.
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.
static ID rb_intern_const(const char *str)
This is a "tiny optimisation" over rb_intern().
ID rb_check_id(volatile VALUE *namep)
Detects if the given name is already interned or not.
ID rb_intern(const char *name)
Finds or creates a symbol of the given name.
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.
void rb_define_virtual_variable(const char *name, rb_gvar_getter_t *getter, rb_gvar_setter_t *setter)
Defines a global variable that is purely function-backended.
void rb_define_hooked_variable(const char *name, VALUE *var, rb_gvar_getter_t *getter, rb_gvar_setter_t *setter)
Identical to rb_define_virtual_variable(), but can also specify a storage.
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.
VALUE type(ANYARGS)
ANYARGS-ed function type.
int st_foreach(st_table *q, int_type *w, st_data_t e)
Iteration over the given table.
#define RARRAY_LEN
Just another name of rb_array_len.
#define RARRAY_CONST_PTR_TRANSIENT
Just another name of rb_array_const_ptr_transient.
#define RARRAY_AREF(a, i)
#define RBASIC(obj)
Convenient casting macro.
#define StringValue(v)
Ensures that the parameter object is a String.
#define StringValuePtr(v)
Identical to StringValue, except it returns a char*.
static long RSTRING_LEN(VALUE str)
Queries the length of the string.
static char * RSTRING_PTR(VALUE str)
Queries the contents pointer of the string.
VALUE rb_get_path(VALUE obj)
Converts an object to a path.
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.
static void Check_Type(VALUE v, enum ruby_value_type t)
Identical to RB_TYPE_P(), except it raises exceptions on predication failure.
static bool RB_TYPE_P(VALUE obj, enum ruby_value_type t)
Queries if the given object is of given type.