Ruby 2.7.0p0(2019-12-25revision647ee6f091eafcce70ffb75ddf7e121e192ab217)

load.c
Go to the documentation of this file.
1 /*
2 * load methods from eval.c
3 */
4
5 #include "ruby/encoding.h"
6 #include "ruby/util.h"
7 #include "internal.h"
8 #include "dln.h"
9 #include "eval_intern.h"
10 #include "probes.h"
11 #include "iseq.h"
12
13 static VALUE ruby_dln_librefs;
14
15 #define IS_RBEXT(e) (strcmp((e), ".rb") == 0)
16 #define IS_SOEXT(e) (strcmp((e), ".so") == 0 || strcmp((e), ".o") == 0)
17 #ifdef DLEXT2
18 #define IS_DLEXT(e) (strcmp((e), DLEXT) == 0 || strcmp((e), DLEXT2) == 0)
19 #else
20 #define IS_DLEXT(e) (strcmp((e), DLEXT) == 0)
21 #endif
22
23 static const char *const loadable_ext[] = {
24 ".rb", DLEXT,
25 #ifdef DLEXT2
26 DLEXT2,
27 #endif
28 0
29 };
30
31 enum expand_type {
32 EXPAND_ALL,
33 EXPAND_RELATIVE,
34 EXPAND_HOME,
35 EXPAND_NON_CACHE
36 };
37
38 /* Construct expanded load path and store it to cache.
39 We rebuild load path partially if the cache is invalid.
40 We don't cache non string object and expand it every time. We ensure that
41 string objects in $LOAD_PATH are frozen.
42 */
43 static void
44 rb_construct_expanded_load_path(enum expand_type type, int *has_relative, int *has_non_cache)
45 {
46 rb_vm_t *vm = GET_VM();
47 VALUE load_path = vm->load_path;
48 VALUE expanded_load_path = vm->expanded_load_path;
49 VALUE ary;
50 long i;
51
52 ary = rb_ary_tmp_new(RARRAY_LEN(load_path));
53 for (i = 0; i < RARRAY_LEN(load_path); ++i) {
54 VALUE path, as_str, expanded_path;
55 int is_string, non_cache;
56 char *as_cstr;
57 as_str = path = RARRAY_AREF(load_path, i);
58 is_string = RB_TYPE_P(path, T_STRING) ? 1 : 0;
59 non_cache = !is_string ? 1 : 0;
60 as_str = rb_get_path_check_to_string(path);
61 as_cstr = RSTRING_PTR(as_str);
62
63 if (!non_cache) {
64 if ((type == EXPAND_RELATIVE &&
65 rb_is_absolute_path(as_cstr)) ||
66 (type == EXPAND_HOME &&
67 (!as_cstr[0] || as_cstr[0] != '~')) ||
68 (type == EXPAND_NON_CACHE)) {
69 /* Use cached expanded path. */
70 rb_ary_push(ary, RARRAY_AREF(expanded_load_path, i));
71 continue;
72 }
73 }
74 if (!*has_relative && !rb_is_absolute_path(as_cstr))
75 *has_relative = 1;
76 if (!*has_non_cache && non_cache)
77 *has_non_cache = 1;
78 /* Freeze only string object. We expand other objects every time. */
79 if (is_string)
80 rb_str_freeze(path);
81 as_str = rb_get_path_check_convert(as_str);
82 expanded_path = rb_check_realpath(Qnil, as_str, NULL);
83 if (NIL_P(expanded_path)) expanded_path = as_str;
84 rb_ary_push(ary, rb_fstring(expanded_path));
85 }
86 rb_obj_freeze(ary);
87 vm->expanded_load_path = ary;
88 rb_ary_replace(vm->load_path_snapshot, vm->load_path);
89 }
90
91 VALUE
92 rb_get_expanded_load_path(void)
93 {
94 rb_vm_t *vm = GET_VM();
95 const VALUE non_cache = Qtrue;
96
97 if (!rb_ary_shared_with_p(vm->load_path_snapshot, vm->load_path)) {
98 /* The load path was modified. Rebuild the expanded load path. */
99 int has_relative = 0, has_non_cache = 0;
100 rb_construct_expanded_load_path(EXPAND_ALL, &has_relative, &has_non_cache);
101 if (has_relative) {
102 vm->load_path_check_cache = rb_dir_getwd_ospath();
103 }
104 else if (has_non_cache) {
105 /* Non string object. */
106 vm->load_path_check_cache = non_cache;
107 }
108 else {
109 vm->load_path_check_cache = 0;
110 }
111 }
112 else if (vm->load_path_check_cache == non_cache) {
113 int has_relative = 1, has_non_cache = 1;
114 /* Expand only non-cacheable objects. */
115 rb_construct_expanded_load_path(EXPAND_NON_CACHE,
116 &has_relative, &has_non_cache);
117 }
118 else if (vm->load_path_check_cache) {
119 int has_relative = 1, has_non_cache = 1;
120 VALUE cwd = rb_dir_getwd_ospath();
121 if (!rb_str_equal(vm->load_path_check_cache, cwd)) {
122 /* Current working directory or filesystem encoding was changed.
123 Expand relative load path and non-cacheable objects again. */
124 vm->load_path_check_cache = cwd;
125 rb_construct_expanded_load_path(EXPAND_RELATIVE,
126 &has_relative, &has_non_cache);
127 }
128 else {
129 /* Expand only tilde (User HOME) and non-cacheable objects. */
130 rb_construct_expanded_load_path(EXPAND_HOME,
131 &has_relative, &has_non_cache);
132 }
133 }
134 return vm->expanded_load_path;
135 }
136
137 static VALUE
138 load_path_getter(ID id, VALUE * p)
139 {
140 rb_vm_t *vm = (void *)p;
141 return vm->load_path;
142 }
143
144 static VALUE
145 get_loaded_features(void)
146 {
147 return GET_VM()->loaded_features;
148 }
149
150 static VALUE
151 get_LOADED_FEATURES(ID _x, VALUE *_y)
152 {
153 return get_loaded_features();
154 }
155
156 static void
157 reset_loaded_features_snapshot(void)
158 {
159 rb_vm_t *vm = GET_VM();
160 rb_ary_replace(vm->loaded_features_snapshot, vm->loaded_features);
161 }
162
163 static struct st_table *
164 get_loaded_features_index_raw(void)
165 {
166 return GET_VM()->loaded_features_index;
167 }
168
169 static st_table *
170 get_loading_table(void)
171 {
172 return GET_VM()->loading_table;
173 }
174
175 static st_data_t
176 feature_key(const char *str, size_t len)
177 {
178 return st_hash(str, len, 0xfea7009e);
179 }
180
181 static void
182 features_index_add_single(const char* str, size_t len, VALUE offset)
183 {
184 struct st_table *features_index;
185 VALUE this_feature_index = Qnil;
186 st_data_t short_feature_key;
187
188 Check_Type(offset, T_FIXNUM);
189 short_feature_key = feature_key(str, len);
190
191 features_index = get_loaded_features_index_raw();
192 st_lookup(features_index, short_feature_key, (st_data_t *)&this_feature_index);
193
194 if (NIL_P(this_feature_index)) {
195 st_insert(features_index, short_feature_key, (st_data_t)offset);
196 }
197 else if (RB_TYPE_P(this_feature_index, T_FIXNUM)) {
198 VALUE feature_indexes[2];
199 feature_indexes[0] = this_feature_index;
200 feature_indexes[1] = offset;
201 this_feature_index = (VALUE)xcalloc(1, sizeof(struct RArray));
202 RBASIC(this_feature_index)->flags = T_ARRAY; /* fake VALUE, do not mark/sweep */
203 rb_ary_cat(this_feature_index, feature_indexes, numberof(feature_indexes));
204 st_insert(features_index, short_feature_key, (st_data_t)this_feature_index);
205 }
206 else {
207 Check_Type(this_feature_index, T_ARRAY);
208 rb_ary_push(this_feature_index, offset);
209 }
210 }
211
212 /* Add to the loaded-features index all the required entries for
213 `feature`, located at `offset` in $LOADED_FEATURES. We add an
214 index entry at each string `short_feature` for which
215 feature == "#{prefix}#{short_feature}#{ext}"
216 where `ext` is empty or matches %r{^\.[^./]*$}, and `prefix` is empty
217 or ends in '/'. This maintains the invariant that `rb_feature_p()`
218 relies on for its fast lookup.
219 */
220 static void
221 features_index_add(VALUE feature, VALUE offset)
222 {
223 const char *feature_str, *feature_end, *ext, *p;
224
225 feature_str = StringValuePtr(feature);
226 feature_end = feature_str + RSTRING_LEN(feature);
227
228 for (ext = feature_end; ext > feature_str; ext--)
229 if (*ext == '.' || *ext == '/')
230 break;
231 if (*ext != '.')
232 ext = NULL;
233 /* Now `ext` points to the only string matching %r{^\.[^./]*$} that is
234 at the end of `feature`, or is NULL if there is no such string. */
235
236 p = ext ? ext : feature_end;
237 while (1) {
238 p--;
239 while (p >= feature_str && *p != '/')
240 p--;
241 if (p < feature_str)
242 break;
243 /* Now *p == '/'. We reach this point for every '/' in `feature`. */
244 features_index_add_single(p + 1, feature_end - p - 1, offset);
245 if (ext) {
246 features_index_add_single(p + 1, ext - p - 1, offset);
247 }
248 }
249 features_index_add_single(feature_str, feature_end - feature_str, offset);
250 if (ext) {
251 features_index_add_single(feature_str, ext - feature_str, offset);
252 }
253 }
254
255 static int
256 loaded_features_index_clear_i(st_data_t key, st_data_t val, st_data_t arg)
257 {
258 VALUE obj = (VALUE)val;
259 if (!SPECIAL_CONST_P(obj)) {
260 rb_ary_free(obj);
261 ruby_sized_xfree((void *)obj, sizeof(struct RArray));
262 }
263 return ST_DELETE;
264 }
265
266 static st_table *
267 get_loaded_features_index(void)
268 {
269 VALUE features;
270 int i;
271 rb_vm_t *vm = GET_VM();
272
273 if (!rb_ary_shared_with_p(vm->loaded_features_snapshot, vm->loaded_features)) {
274 /* The sharing was broken; something (other than us in rb_provide_feature())
275 modified loaded_features. Rebuild the index. */
276 st_foreach(vm->loaded_features_index, loaded_features_index_clear_i, 0);
277 features = vm->loaded_features;
278 for (i = 0; i < RARRAY_LEN(features); i++) {
279 VALUE entry, as_str;
280 as_str = entry = rb_ary_entry(features, i);
281 StringValue(as_str);
282 as_str = rb_fstring(rb_str_freeze(as_str));
283 if (as_str != entry)
284 rb_ary_store(features, i, as_str);
285 features_index_add(as_str, INT2FIX(i));
286 }
287 reset_loaded_features_snapshot();
288 }
289 return vm->loaded_features_index;
290 }
291
292 /* This searches `load_path` for a value such that
293 name == "#{load_path[i]}/#{feature}"
294 if `feature` is a suffix of `name`, or otherwise
295 name == "#{load_path[i]}/#{feature}#{ext}"
296 for an acceptable string `ext`. It returns
297 `load_path[i].to_str` if found, else 0.
298
299 If type is 's', then `ext` is acceptable only if IS_DLEXT(ext);
300 if 'r', then only if IS_RBEXT(ext); otherwise `ext` may be absent
301 or have any value matching `%r{^\.[^./]*$}`.
302 */
303 static VALUE
304 loaded_feature_path(const char *name, long vlen, const char *feature, long len,
305 int type, VALUE load_path)
306 {
307 long i;
308 long plen;
309 const char *e;
310
311 if (vlen < len+1) return 0;
312 if (strchr(feature, '.') && !strncmp(name+(vlen-len), feature, len)) {
313 plen = vlen - len;
314 }
315 else {
316 for (e = name + vlen; name != e && *e != '.' && *e != '/'; --e);
317 if (*e != '.' ||
318 e-name < len ||
319 strncmp(e-len, feature, len))
320 return 0;
321 plen = e - name - len;
322 }
323 if (plen > 0 && name[plen-1] != '/') {
324 return 0;
325 }
326 if (type == 's' ? !IS_DLEXT(&name[plen+len]) :
327 type == 'r' ? !IS_RBEXT(&name[plen+len]) :
328 0) {
329 return 0;
330 }
331 /* Now name == "#{prefix}/#{feature}#{ext}" where ext is acceptable
332 (possibly empty) and prefix is some string of length plen. */
333
334 if (plen > 0) --plen; /* exclude '.' */
335 for (i = 0; i < RARRAY_LEN(load_path); ++i) {
336 VALUE p = RARRAY_AREF(load_path, i);
337 const char *s = StringValuePtr(p);
338 long n = RSTRING_LEN(p);
339
340 if (n != plen) continue;
341 if (n && strncmp(name, s, n)) continue;
342 return p;
343 }
344 return 0;
345 }
346
347 struct loaded_feature_searching {
348 const char *name;
349 long len;
350 int type;
351 VALUE load_path;
352 const char *result;
353 };
354
355 static int
356 loaded_feature_path_i(st_data_t v, st_data_t b, st_data_t f)
357 {
358 const char *s = (const char *)v;
359 struct loaded_feature_searching *fp = (struct loaded_feature_searching *)f;
360 VALUE p = loaded_feature_path(s, strlen(s), fp->name, fp->len,
361 fp->type, fp->load_path);
362 if (!p) return ST_CONTINUE;
363 fp->result = s;
364 return ST_STOP;
365 }
366
367 static int
368 rb_feature_p(const char *feature, const char *ext, int rb, int expanded, const char **fn)
369 {
370 VALUE features, this_feature_index = Qnil, v, p, load_path = 0;
371 const char *f, *e;
372 long i, len, elen, n;
373 st_table *loading_tbl, *features_index;
374 st_data_t data;
375 st_data_t key;
376 int type;
377
378 if (fn) *fn = 0;
379 if (ext) {
380 elen = strlen(ext);
381 len = strlen(feature) - elen;
382 type = rb ? 'r' : 's';
383 }
384 else {
385 len = strlen(feature);
386 elen = 0;
387 type = 0;
388 }
389 features = get_loaded_features();
390 features_index = get_loaded_features_index();
391
392 key = feature_key(feature, strlen(feature));
393 st_lookup(features_index, key, (st_data_t *)&this_feature_index);
394 /* We search `features` for an entry such that either
395 "#{features[i]}" == "#{load_path[j]}/#{feature}#{e}"
396 for some j, or
397 "#{features[i]}" == "#{feature}#{e}"
398 Here `e` is an "allowed" extension -- either empty or one
399 of the extensions accepted by IS_RBEXT, IS_SOEXT, or
400 IS_DLEXT. Further, if `ext && rb` then `IS_RBEXT(e)`,
401 and if `ext && !rb` then `IS_SOEXT(e) || IS_DLEXT(e)`.
402
403 If `expanded`, then only the latter form (without load_path[j])
404 is accepted. Otherwise either form is accepted, *unless* `ext`
405 is false and an otherwise-matching entry of the first form is
406 preceded by an entry of the form
407 "#{features[i2]}" == "#{load_path[j2]}/#{feature}#{e2}"
408 where `e2` matches %r{^\.[^./]*$} but is not an allowed extension.
409 After a "distractor" entry of this form, only entries of the
410 form "#{feature}#{e}" are accepted.
411
412 In `rb_provide_feature()` and `get_loaded_features_index()` we
413 maintain an invariant that the array `this_feature_index` will
414 point to every entry in `features` which has the form
415 "#{prefix}#{feature}#{e}"
416 where `e` is empty or matches %r{^\.[^./]*$}, and `prefix` is empty
417 or ends in '/'. This includes both match forms above, as well
418 as any distractors, so we may ignore all other entries in `features`.
419 */
420 if (!NIL_P(this_feature_index)) {
421 for (i = 0; ; i++) {
422 VALUE entry;
423 long index;
424 if (RB_TYPE_P(this_feature_index, T_ARRAY)) {
425 if (i >= RARRAY_LEN(this_feature_index)) break;
426 entry = RARRAY_AREF(this_feature_index, i);
427 }
428 else {
429 if (i > 0) break;
430 entry = this_feature_index;
431 }
432 index = FIX2LONG(entry);
433
434 v = RARRAY_AREF(features, index);
435 f = StringValuePtr(v);
436 if ((n = RSTRING_LEN(v)) < len) continue;
437 if (strncmp(f, feature, len) != 0) {
438 if (expanded) continue;
439 if (!load_path) load_path = rb_get_expanded_load_path();
440 if (!(p = loaded_feature_path(f, n, feature, len, type, load_path)))
441 continue;
442 expanded = 1;
443 f += RSTRING_LEN(p) + 1;
444 }
445 if (!*(e = f + len)) {
446 if (ext) continue;
447 return 'u';
448 }
449 if (*e != '.') continue;
450 if ((!rb || !ext) && (IS_SOEXT(e) || IS_DLEXT(e))) {
451 return 's';
452 }
453 if ((rb || !ext) && (IS_RBEXT(e))) {
454 return 'r';
455 }
456 }
457 }
458
459 loading_tbl = get_loading_table();
460 f = 0;
461 if (!expanded) {
462 struct loaded_feature_searching fs;
463 fs.name = feature;
464 fs.len = len;
465 fs.type = type;
466 fs.load_path = load_path ? load_path : rb_get_expanded_load_path();
467 fs.result = 0;
468 st_foreach(loading_tbl, loaded_feature_path_i, (st_data_t)&fs);
469 if ((f = fs.result) != 0) {
470 if (fn) *fn = f;
471 goto loading;
472 }
473 }
474 if (st_get_key(loading_tbl, (st_data_t)feature, &data)) {
475 if (fn) *fn = (const char*)data;
476 loading:
477 if (!ext) return 'u';
478 return !IS_RBEXT(ext) ? 's' : 'r';
479 }
480 else {
481 VALUE bufstr;
482 char *buf;
483 static const char so_ext[][4] = {
484 ".so", ".o",
485 };
486
487 if (ext && *ext) return 0;
488 bufstr = rb_str_tmp_new(len + DLEXT_MAXLEN);
489 buf = RSTRING_PTR(bufstr);
490 MEMCPY(buf, feature, char, len);
491 for (i = 0; (e = loadable_ext[i]) != 0; i++) {
492 strlcpy(buf + len, e, DLEXT_MAXLEN + 1);
493 if (st_get_key(loading_tbl, (st_data_t)buf, &data)) {
494 rb_str_resize(bufstr, 0);
495 if (fn) *fn = (const char*)data;
496 return i ? 's' : 'r';
497 }
498 }
499 for (i = 0; i < numberof(so_ext); i++) {
500 strlcpy(buf + len, so_ext[i], DLEXT_MAXLEN + 1);
501 if (st_get_key(loading_tbl, (st_data_t)buf, &data)) {
502 rb_str_resize(bufstr, 0);
503 if (fn) *fn = (const char*)data;
504 return 's';
505 }
506 }
507 rb_str_resize(bufstr, 0);
508 }
509 return 0;
510 }
511
512 int
513 rb_provided(const char *feature)
514 {
515 return rb_feature_provided(feature, 0);
516 }
517
518 int
519 rb_feature_provided(const char *feature, const char **loading)
520 {
521 const char *ext = strrchr(feature, '.');
522 VALUE fullpath = 0;
523
524 if (*feature == '.' &&
525 (feature[1] == '/' || strncmp(feature+1, "./", 2) == 0)) {
526 fullpath = rb_file_expand_path_fast(rb_get_path(rb_str_new2(feature)), Qnil);
527 feature = RSTRING_PTR(fullpath);
528 }
529 if (ext && !strchr(ext, '/')) {
530 if (IS_RBEXT(ext)) {
531 if (rb_feature_p(feature, ext, TRUE, FALSE, loading)) return TRUE;
532 return FALSE;
533 }
534 else if (IS_SOEXT(ext) || IS_DLEXT(ext)) {
535 if (rb_feature_p(feature, ext, FALSE, FALSE, loading)) return TRUE;
536 return FALSE;
537 }
538 }
539 if (rb_feature_p(feature, 0, TRUE, FALSE, loading))
540 return TRUE;
541 RB_GC_GUARD(fullpath);
542 return FALSE;
543 }
544
545 static void
546 rb_provide_feature(VALUE feature)
547 {
548 VALUE features;
549
550 features = get_loaded_features();
551 if (OBJ_FROZEN(features)) {
552 rb_raise(rb_eRuntimeError,
553 "$LOADED_FEATURES is frozen; cannot append feature");
554 }
555 rb_str_freeze(feature);
556
557 rb_ary_push(features, rb_fstring(feature));
558 features_index_add(feature, INT2FIX(RARRAY_LEN(features)-1));
559 reset_loaded_features_snapshot();
560 }
561
562 void
563 rb_provide(const char *feature)
564 {
565 rb_provide_feature(rb_fstring_cstr(feature));
566 }
567
568 NORETURN(static void load_failed(VALUE));
569
570 static inline void
571 load_iseq_eval(rb_execution_context_t *ec, VALUE fname)
572 {
573 const rb_iseq_t *iseq = rb_iseq_load_iseq(fname);
574
575 if (!iseq) {
576 rb_ast_t *ast;
577 VALUE parser = rb_parser_new();
578 rb_parser_set_context(parser, NULL, FALSE);
579 ast = (rb_ast_t *)rb_parser_load_file(parser, fname);
580 iseq = rb_iseq_new_top(&ast->body, rb_fstring_lit("<top (required)>"),
581 fname, rb_realpath_internal(Qnil, fname, 1), NULL);
582 rb_ast_dispose(ast);
583 }
584 rb_exec_event_hook_script_compiled(ec, iseq, Qnil);
585 rb_iseq_eval(iseq);
586 }
587
588 static inline enum ruby_tag_type
589 load_wrapping(rb_execution_context_t *ec, VALUE fname)
590 {
591 enum ruby_tag_type state;
592 rb_thread_t *th = rb_ec_thread_ptr(ec);
593 volatile VALUE wrapper = th->top_wrapper;
594 volatile VALUE self = th->top_self;
595 #if !defined __GNUC__
596 rb_thread_t *volatile th0 = th;
597 #endif
598
599 ec->errinfo = Qnil; /* ensure */
600
601 /* load in anonymous module as toplevel */
602 th->top_self = rb_obj_clone(rb_vm_top_self());
603 th->top_wrapper = rb_module_new();
604 rb_extend_object(th->top_self, th->top_wrapper);
605
606 EC_PUSH_TAG(ec);
607 state = EC_EXEC_TAG();
608 if (state == TAG_NONE) {
609 load_iseq_eval(ec, fname);
610 }
611 EC_POP_TAG();
612
613 #if !defined __GNUC__
614 th = th0;
615 fname = RB_GC_GUARD(fname);
616 #endif
617 th->top_self = self;
618 th->top_wrapper = wrapper;
619 return state;
620 }
621
622 static inline void
623 raise_load_if_failed(rb_execution_context_t *ec, enum ruby_tag_type state)
624 {
625 if (state) {
626 rb_vm_jump_tag_but_local_jump(state);
627 }
628
629 if (!NIL_P(ec->errinfo)) {
630 rb_exc_raise(ec->errinfo);
631 }
632 }
633
634 static void
635 rb_load_internal(VALUE fname, int wrap)
636 {
637 rb_execution_context_t *ec = GET_EC();
638 enum ruby_tag_type state = TAG_NONE;
639 if (wrap) {
640 state = load_wrapping(ec, fname);
641 }
642 else {
643 load_iseq_eval(ec, fname);
644 }
645 raise_load_if_failed(ec, state);
646 }
647
648 void
649 rb_load(VALUE fname, int wrap)
650 {
651 VALUE tmp = rb_find_file(FilePathValue(fname));
652 if (!tmp) load_failed(fname);
653 rb_load_internal(tmp, wrap);
654 }
655
656 void
657 rb_load_protect(VALUE fname, int wrap, int *pstate)
658 {
659 enum ruby_tag_type state;
660
661 EC_PUSH_TAG(GET_EC());
662 if ((state = EC_EXEC_TAG()) == TAG_NONE) {
663 rb_load(fname, wrap);
664 }
665 EC_POP_TAG();
666
667 if (state != TAG_NONE) *pstate = state;
668 }
669
670 /*
671 * call-seq:
672 * load(filename, wrap=false) -> true
673 *
674 * Loads and executes the Ruby
675 * program in the file _filename_. If the filename does not
676 * resolve to an absolute path, the file is searched for in the library
677 * directories listed in <code>$:</code>. If the optional _wrap_
678 * parameter is +true+, the loaded script will be executed
679 * under an anonymous module, protecting the calling program's global
680 * namespace. In no circumstance will any local variables in the loaded
681 * file be propagated to the loading environment.
682 */
683
684 static VALUE
685 rb_f_load(int argc, VALUE *argv, VALUE _)
686 {
687 VALUE fname, wrap, path, orig_fname;
688
689 rb_scan_args(argc, argv, "11", &fname, &wrap);
690
691 orig_fname = rb_get_path_check_to_string(fname);
692 fname = rb_str_encode_ospath(orig_fname);
693 RUBY_DTRACE_HOOK(LOAD_ENTRY, RSTRING_PTR(orig_fname));
694
695 path = rb_find_file(fname);
696 if (!path) {
697 if (!rb_file_load_ok(RSTRING_PTR(fname)))
698 load_failed(orig_fname);
699 path = fname;
700 }
701 rb_load_internal(path, RTEST(wrap));
702
703 RUBY_DTRACE_HOOK(LOAD_RETURN, RSTRING_PTR(orig_fname));
704
705 return Qtrue;
706 }
707
708 static char *
709 load_lock(const char *ftptr)
710 {
711 st_data_t data;
712 st_table *loading_tbl = get_loading_table();
713
714 if (!st_lookup(loading_tbl, (st_data_t)ftptr, &data)) {
715 /* partial state */
716 ftptr = ruby_strdup(ftptr);
717 data = (st_data_t)rb_thread_shield_new();
718 st_insert(loading_tbl, (st_data_t)ftptr, data);
719 return (char *)ftptr;
720 }
721 else if (imemo_type_p(data, imemo_memo)) {
722 struct MEMO *memo = MEMO_CAST(data);
723 void (*init)(void) = memo->u3.func;
724 data = (st_data_t)rb_thread_shield_new();
725 st_insert(loading_tbl, (st_data_t)ftptr, data);
726 (*init)();
727 return (char *)"";
728 }
729 if (RTEST(ruby_verbose)) {
730 VALUE warning = rb_warning_string("loading in progress, circular require considered harmful - %s", ftptr);
731 rb_backtrace_each(rb_str_append, warning);
732 rb_warning("%"PRIsVALUE, warning);
733 }
734 switch (rb_thread_shield_wait((VALUE)data)) {
735 case Qfalse:
736 case Qnil:
737 return 0;
738 }
739 return (char *)ftptr;
740 }
741
742 static int
743 release_thread_shield(st_data_t *key, st_data_t *value, st_data_t done, int existing)
744 {
745 VALUE thread_shield = (VALUE)*value;
746 if (!existing) return ST_STOP;
747 if (done) {
748 rb_thread_shield_destroy(thread_shield);
749 /* Delete the entry even if there are waiting threads, because they
750 * won't load the file and won't delete the entry. */
751 }
752 else if (rb_thread_shield_release(thread_shield)) {
753 /* still in-use */
754 return ST_CONTINUE;
755 }
756 xfree((char *)*key);
757 return ST_DELETE;
758 }
759
760 static void
761 load_unlock(const char *ftptr, int done)
762 {
763 if (ftptr) {
764 st_data_t key = (st_data_t)ftptr;
765 st_table *loading_tbl = get_loading_table();
766
767 st_update(loading_tbl, key, release_thread_shield, done);
768 }
769 }
770
771
772 /*
773 * call-seq:
774 * require(name) -> true or false
775 *
776 * Loads the given +name+, returning +true+ if successful and +false+ if the
777 * feature is already loaded.
778 *
779 * If the filename does not resolve to an absolute path, it will be searched
780 * for in the directories listed in <code>$LOAD_PATH</code> (<code>$:</code>).
781 *
782 * If the filename has the extension ".rb", it is loaded as a source file; if
783 * the extension is ".so", ".o", or ".dll", or the default shared library
784 * extension on the current platform, Ruby loads the shared library as a
785 * Ruby extension. Otherwise, Ruby tries adding ".rb", ".so", and so on
786 * to the name until found. If the file named cannot be found, a LoadError
787 * will be raised.
788 *
789 * For Ruby extensions the filename given may use any shared library
790 * extension. For example, on Linux the socket extension is "socket.so" and
791 * <code>require 'socket.dll'</code> will load the socket extension.
792 *
793 * The absolute path of the loaded file is added to
794 * <code>$LOADED_FEATURES</code> (<code>$"</code>). A file will not be
795 * loaded again if its path already appears in <code>$"</code>. For example,
796 * <code>require 'a'; require './a'</code> will not load <code>a.rb</code>
797 * again.
798 *
799 * require "my-library.rb"
800 * require "db-driver"
801 *
802 * Any constants or globals within the loaded source file will be available
803 * in the calling program's global namespace. However, local variables will
804 * not be propagated to the loading environment.
805 *
806 */
807
808 VALUE
809 rb_f_require(VALUE obj, VALUE fname)
810 {
811 return rb_require_string(fname);
812 }
813
814 /*
815 * call-seq:
816 * require_relative(string) -> true or false
817 *
818 * Ruby tries to load the library named _string_ relative to the requiring
819 * file's path. If the file's path cannot be determined a LoadError is raised.
820 * If a file is loaded +true+ is returned and false otherwise.
821 */
822 VALUE
823 rb_f_require_relative(VALUE obj, VALUE fname)
824 {
825 VALUE base = rb_current_realfilepath();
826 if (NIL_P(base)) {
827 rb_loaderror("cannot infer basepath");
828 }
829 base = rb_file_dirname(base);
830 return rb_require_string(rb_file_absolute_path(fname, base));
831 }
832
833 typedef int (*feature_func)(const char *feature, const char *ext, int rb, int expanded, const char **fn);
834
835 static int
836 search_required(VALUE fname, volatile VALUE *path, feature_func rb_feature_p)
837 {
838 VALUE tmp;
839 char *ext, *ftptr;
840 int type, ft = 0;
841 const char *loading;
842
843 *path = 0;
844 ext = strrchr(ftptr = RSTRING_PTR(fname), '.');
845 if (ext && !strchr(ext, '/')) {
846 if (IS_RBEXT(ext)) {
847 if (rb_feature_p(ftptr, ext, TRUE, FALSE, &loading)) {
848 if (loading) *path = rb_filesystem_str_new_cstr(loading);
849 return 'r';
850 }
851 if ((tmp = rb_find_file(fname)) != 0) {
852 ext = strrchr(ftptr = RSTRING_PTR(tmp), '.');
853 if (!rb_feature_p(ftptr, ext, TRUE, TRUE, &loading) || loading)
854 *path = tmp;
855 return 'r';
856 }
857 return 0;
858 }
859 else if (IS_SOEXT(ext)) {
860 if (rb_feature_p(ftptr, ext, FALSE, FALSE, &loading)) {
861 if (loading) *path = rb_filesystem_str_new_cstr(loading);
862 return 's';
863 }
864 tmp = rb_str_subseq(fname, 0, ext - RSTRING_PTR(fname));
865 #ifdef DLEXT2
866 OBJ_FREEZE(tmp);
867 if (rb_find_file_ext(&tmp, loadable_ext + 1)) {
868 ext = strrchr(ftptr = RSTRING_PTR(tmp), '.');
869 if (!rb_feature_p(ftptr, ext, FALSE, TRUE, &loading) || loading)
870 *path = tmp;
871 return 's';
872 }
873 #else
874 rb_str_cat2(tmp, DLEXT);
875 OBJ_FREEZE(tmp);
876 if ((tmp = rb_find_file(tmp)) != 0) {
877 ext = strrchr(ftptr = RSTRING_PTR(tmp), '.');
878 if (!rb_feature_p(ftptr, ext, FALSE, TRUE, &loading) || loading)
879 *path = tmp;
880 return 's';
881 }
882 #endif
883 }
884 else if (IS_DLEXT(ext)) {
885 if (rb_feature_p(ftptr, ext, FALSE, FALSE, &loading)) {
886 if (loading) *path = rb_filesystem_str_new_cstr(loading);
887 return 's';
888 }
889 if ((tmp = rb_find_file(fname)) != 0) {
890 ext = strrchr(ftptr = RSTRING_PTR(tmp), '.');
891 if (!rb_feature_p(ftptr, ext, FALSE, TRUE, &loading) || loading)
892 *path = tmp;
893 return 's';
894 }
895 }
896 }
897 else if ((ft = rb_feature_p(ftptr, 0, FALSE, FALSE, &loading)) == 'r') {
898 if (loading) *path = rb_filesystem_str_new_cstr(loading);
899 return 'r';
900 }
901 tmp = fname;
902 type = rb_find_file_ext(&tmp, loadable_ext);
903 switch (type) {
904 case 0:
905 if (ft)
906 goto statically_linked;
907 ftptr = RSTRING_PTR(tmp);
908 return rb_feature_p(ftptr, 0, FALSE, TRUE, 0);
909
910 default:
911 if (ft) {
912 statically_linked:
913 if (loading) *path = rb_filesystem_str_new_cstr(loading);
914 return ft;
915 }
916 /* fall through */
917 case 1:
918 ext = strrchr(ftptr = RSTRING_PTR(tmp), '.');
919 if (rb_feature_p(ftptr, ext, !--type, TRUE, &loading) && !loading)
920 break;
921 *path = tmp;
922 }
923 return type ? 's' : 'r';
924 }
925
926 static void
927 load_failed(VALUE fname)
928 {
929 rb_load_fail(fname, "cannot load such file");
930 }
931
932 static VALUE
933 load_ext(VALUE path)
934 {
935 rb_scope_visibility_set(METHOD_VISI_PUBLIC);
936 return (VALUE)dln_load(RSTRING_PTR(path));
937 }
938
939 static int
940 no_feature_p(const char *feature, const char *ext, int rb, int expanded, const char **fn)
941 {
942 return 0;
943 }
944
945 // Documented in doc/globals.rdoc
946 VALUE
947 rb_resolve_feature_path(VALUE klass, VALUE fname)
948 {
949 VALUE path;
950 int found;
951 VALUE sym;
952
953 fname = rb_get_path(fname);
954 path = rb_str_encode_ospath(fname);
955 found = search_required(path, &path, no_feature_p);
956
957 switch (found) {
958 case 'r':
959 sym = ID2SYM(rb_intern("rb"));
960 break;
961 case 's':
962 sym = ID2SYM(rb_intern("so"));
963 break;
964 default:
965 load_failed(fname);
966 }
967
968 return rb_ary_new_from_args(2, sym, path);
969 }
970
971 /*
972 * returns
973 * 0: if already loaded (false)
974 * 1: successfully loaded (true)
975 * <0: not found (LoadError)
976 * >1: exception
977 */
978 static int
979 require_internal(rb_execution_context_t *ec, VALUE fname, int exception)
980 {
981 volatile int result = -1;
982 rb_thread_t *th = rb_ec_thread_ptr(ec);
983 volatile VALUE wrapper = th->top_wrapper;
984 volatile VALUE self = th->top_self;
985 volatile VALUE errinfo = ec->errinfo;
986 enum ruby_tag_type state;
987 char *volatile ftptr = 0;
988 VALUE path;
989
990 fname = rb_get_path(fname);
991 path = rb_str_encode_ospath(fname);
992 RUBY_DTRACE_HOOK(REQUIRE_ENTRY, RSTRING_PTR(fname));
993
994 EC_PUSH_TAG(ec);
995 ec->errinfo = Qnil; /* ensure */
996 th->top_wrapper = 0;
997 if ((state = EC_EXEC_TAG()) == TAG_NONE) {
998 long handle;
999 int found;
1000
1001 RUBY_DTRACE_HOOK(FIND_REQUIRE_ENTRY, RSTRING_PTR(fname));
1002 found = search_required(path, &path, rb_feature_p);
1003 RUBY_DTRACE_HOOK(FIND_REQUIRE_RETURN, RSTRING_PTR(fname));
1004
1005 if (found) {
1006 if (!path || !(ftptr = load_lock(RSTRING_PTR(path)))) {
1007 result = 0;
1008 }
1009 else if (!*ftptr) {
1010 rb_provide_feature(path);
1011 result = TAG_RETURN;
1012 }
1013 else {
1014 switch (found) {
1015 case 'r':
1016 load_iseq_eval(ec, path);
1017 break;
1018
1019 case 's':
1020 handle = (long)rb_vm_call_cfunc(rb_vm_top_self(), load_ext,
1021 path, VM_BLOCK_HANDLER_NONE, path);
1022 rb_ary_push(ruby_dln_librefs, LONG2NUM(handle));
1023 break;
1024 }
1025 rb_provide_feature(path);
1026 result = TAG_RETURN;
1027 }
1028 }
1029 }
1030 EC_POP_TAG();
1031 th = rb_ec_thread_ptr(ec);
1032 th->top_self = self;
1033 th->top_wrapper = wrapper;
1034 if (ftptr) load_unlock(RSTRING_PTR(path), !state);
1035
1036 if (state) {
1037 if (state == TAG_FATAL) {
1038 EC_JUMP_TAG(ec, state);
1039 }
1040 else if (exception) {
1041 /* usually state == TAG_RAISE only, except for
1042 * rb_iseq_load_iseq in load_iseq_eval case */
1043 VALUE exc = rb_vm_make_jump_tag_but_local_jump(state, Qundef);
1044 if (!NIL_P(exc)) ec->errinfo = exc;
1045 return TAG_RAISE;
1046 }
1047 else if (state == TAG_RETURN) {
1048 return TAG_RAISE;
1049 }
1050 RB_GC_GUARD(fname);
1051 /* never TAG_RETURN */
1052 return state;
1053 }
1054 if (!NIL_P(ec->errinfo)) {
1055 if (!exception) return TAG_RAISE;
1056 rb_exc_raise(ec->errinfo);
1057 }
1058
1059 ec->errinfo = errinfo;
1060
1061 RUBY_DTRACE_HOOK(REQUIRE_RETURN, RSTRING_PTR(fname));
1062
1063 return result;
1064 }
1065
1066 int
1067 rb_require_internal(VALUE fname)
1068 {
1069 rb_execution_context_t *ec = GET_EC();
1070 return require_internal(ec, fname, 1);
1071 }
1072
1073 int
1074 ruby_require_internal(const char *fname, unsigned int len)
1075 {
1076 struct RString fake;
1077 VALUE str = rb_setup_fake_str(&fake, fname, len, 0);
1078 rb_execution_context_t *ec = GET_EC();
1079 int result = require_internal(ec, str, 0);
1080 rb_set_errinfo(Qnil);
1081 return result == TAG_RETURN ? 1 : result ? -1 : 0;
1082 }
1083
1084 VALUE
1085 rb_require_safe(VALUE fname, int safe)
1086 {
1087 rb_warn("rb_require_safe will be removed in Ruby 3.0");
1088 rb_execution_context_t *ec = GET_EC();
1089 int result = require_internal(ec, fname, 1);
1090
1091 if (result > TAG_RETURN) {
1092 EC_JUMP_TAG(ec, result);
1093 }
1094 if (result < 0) {
1095 load_failed(fname);
1096 }
1097
1098 return result ? Qtrue : Qfalse;
1099 }
1100
1101 VALUE
1102 rb_require_string(VALUE fname)
1103 {
1104 rb_execution_context_t *ec = GET_EC();
1105 int result = require_internal(ec, fname, 1);
1106
1107 if (result > TAG_RETURN) {
1108 EC_JUMP_TAG(ec, result);
1109 }
1110 if (result < 0) {
1111 load_failed(fname);
1112 }
1113
1114 return result ? Qtrue : Qfalse;
1115 }
1116
1117 VALUE
1118 rb_require(const char *fname)
1119 {
1120 return rb_require_string(rb_str_new_cstr(fname));
1121 }
1122
1123 static int
1124 register_init_ext(st_data_t *key, st_data_t *value, st_data_t init, int existing)
1125 {
1126 const char *name = (char *)*key;
1127 if (existing) {
1128 /* already registered */
1129 rb_warn("%s is already registered", name);
1130 }
1131 else {
1132 *value = (st_data_t)MEMO_NEW(0, 0, init);
1133 *key = (st_data_t)ruby_strdup(name);
1134 }
1135 return ST_CONTINUE;
1136 }
1137
1138 RUBY_FUNC_EXPORTED void
1139 ruby_init_ext(const char *name, void (*init)(void))
1140 {
1141 st_table *loading_tbl = get_loading_table();
1142
1143 if (rb_provided(name))
1144 return;
1145 st_update(loading_tbl, (st_data_t)name, register_init_ext, (st_data_t)init);
1146 }
1147
1148 /*
1149 * call-seq:
1150 * mod.autoload(module, filename) -> nil
1151 *
1152 * Registers _filename_ to be loaded (using Kernel::require)
1153 * the first time that _module_ (which may be a String or
1154 * a symbol) is accessed in the namespace of _mod_.
1155 *
1156 * module A
1157 * end
1158 * A.autoload(:B, "b")
1159 * A::B.doit # autoloads "b"
1160 */
1161
1162 static VALUE
1163 rb_mod_autoload(VALUE mod, VALUE sym, VALUE file)
1164 {
1165 ID id = rb_to_id(sym);
1166
1167 FilePathValue(file);
1168 rb_autoload_str(mod, id, file);
1169 return Qnil;
1170 }
1171
1172 /*
1173 * call-seq:
1174 * mod.autoload?(name, inherit=true) -> String or nil
1175 *
1176 * Returns _filename_ to be loaded if _name_ is registered as
1177 * +autoload+ in the namespace of _mod_ or one of its ancestors.
1178 *
1179 * module A
1180 * end
1181 * A.autoload(:B, "b")
1182 * A.autoload?(:B) #=> "b"
1183 *
1184 * If +inherit+ is false, the lookup only checks the autoloads in the receiver:
1185 *
1186 * class A
1187 * autoload :CONST, "const.rb"
1188 * end
1189 *
1190 * class B < A
1191 * end
1192 *
1193 * B.autoload?(:CONST) #=> "const.rb", found in A (ancestor)
1194 * B.autoload?(:CONST, false) #=> nil, not found in B itself
1195 *
1196 */
1197
1198 static VALUE
1199 rb_mod_autoload_p(int argc, VALUE *argv, VALUE mod)
1200 {
1201 int recur = (rb_check_arity(argc, 1, 2) == 1) ? TRUE : RTEST(argv[1]);
1202 VALUE sym = argv[0];
1203
1204 ID id = rb_check_id(&sym);
1205 if (!id) {
1206 return Qnil;
1207 }
1208 return rb_autoload_at_p(mod, id, recur);
1209 }
1210
1211 /*
1212 * call-seq:
1213 * autoload(module, filename) -> nil
1214 *
1215 * Registers _filename_ to be loaded (using Kernel::require)
1216 * the first time that _module_ (which may be a String or
1217 * a symbol) is accessed.
1218 *
1219 * autoload(:MyModule, "/usr/local/lib/modules/my_module.rb")
1220 */
1221
1222 static VALUE
1223 rb_f_autoload(VALUE obj, VALUE sym, VALUE file)
1224 {
1225 VALUE klass = rb_class_real(rb_vm_cbase());
1226 if (NIL_P(klass)) {
1227 rb_raise(rb_eTypeError, "Can not set autoload on singleton class");
1228 }
1229 return rb_mod_autoload(klass, sym, file);
1230 }
1231
1232 /*
1233 * call-seq:
1234 * autoload?(name, inherit=true) -> String or nil
1235 *
1236 * Returns _filename_ to be loaded if _name_ is registered as
1237 * +autoload+.
1238 *
1239 * autoload(:B, "b")
1240 * autoload?(:B) #=> "b"
1241 */
1242
1243 static VALUE
1244 rb_f_autoload_p(int argc, VALUE *argv, VALUE obj)
1245 {
1246 /* use rb_vm_cbase() as same as rb_f_autoload. */
1247 VALUE klass = rb_vm_cbase();
1248 if (NIL_P(klass)) {
1249 return Qnil;
1250 }
1251 return rb_mod_autoload_p(argc, argv, klass);
1252 }
1253
1254 void
1255 Init_load(void)
1256 {
1257 #undef rb_intern
1258 #define rb_intern(str) rb_intern2((str), strlen(str))
1259 rb_vm_t *vm = GET_VM();
1260 static const char var_load_path[] = "$:";
1261 ID id_load_path = rb_intern2(var_load_path, sizeof(var_load_path)-1);
1262
1263 rb_define_hooked_variable(var_load_path, (VALUE*)vm, load_path_getter, rb_gvar_readonly_setter);
1264 rb_alias_variable(rb_intern("$-I"), id_load_path);
1265 rb_alias_variable(rb_intern("$LOAD_PATH"), id_load_path);
1266 vm->load_path = rb_ary_new();
1267 vm->expanded_load_path = rb_ary_tmp_new(0);
1268 vm->load_path_snapshot = rb_ary_tmp_new(0);
1269 vm->load_path_check_cache = 0;
1270 rb_define_singleton_method(vm->load_path, "resolve_feature_path", rb_resolve_feature_path, 1);
1271
1272 rb_define_virtual_variable("$\"", get_LOADED_FEATURES, 0);
1273 rb_define_virtual_variable("$LOADED_FEATURES", get_LOADED_FEATURES, 0);
1274 vm->loaded_features = rb_ary_new();
1275 vm->loaded_features_snapshot = rb_ary_tmp_new(0);
1276 vm->loaded_features_index = st_init_numtable();
1277
1278 rb_define_global_function("load", rb_f_load, -1);
1279 rb_define_global_function("require", rb_f_require, 1);
1280 rb_define_global_function("require_relative", rb_f_require_relative, 1);
1281 rb_define_method(rb_cModule, "autoload", rb_mod_autoload, 2);
1282 rb_define_method(rb_cModule, "autoload?", rb_mod_autoload_p, -1);
1283 rb_define_global_function("autoload", rb_f_autoload, 2);
1284 rb_define_global_function("autoload?", rb_f_autoload_p, -1);
1285
1286 ruby_dln_librefs = rb_ary_tmp_new(0);
1287 rb_gc_register_mark_object(ruby_dln_librefs);
1288 }
expand_type
expand_type
Definition: load.c:31
rb_feature_provided
int rb_feature_provided(const char *feature, const char **loading)
Definition: load.c:519
rb_parser_new
VALUE rb_parser_new(void)
Definition: ripper.c:19224
IS_DLEXT
#define IS_DLEXT(e)
Definition: load.c:20
ID
unsigned long ID
Definition: ruby.h:103
rb_vm_struct::loaded_features_index
struct st_table * loaded_features_index
Definition: vm_core.h:621
void
void
Definition: rb_mjit_min_header-2.7.0.h:13273
rb_fstring
VALUE rb_fstring(VALUE)
Definition: string.c:312
Check_Type
#define Check_Type(v, t)
Definition: ruby.h:595
TRUE
#define TRUE
Definition: nkf.h:175
rb_str_freeze
VALUE rb_str_freeze(VALUE)
Definition: string.c:2616
rb_vm_jump_tag_but_local_jump
void rb_vm_jump_tag_but_local_jump(int state)
Definition: vm.c:1510
rb_iseq_eval
VALUE rb_iseq_eval(const rb_iseq_t *iseq)
Definition: vm.c:2163
rb_check_id
ID rb_check_id(volatile VALUE *)
Returns ID for the given name if it is interned already, or 0.
Definition: symbol.c:919
xcalloc
#define xcalloc
Definition: defines.h:213
rb_file_expand_path_fast
VALUE rb_file_expand_path_fast(VALUE fname, VALUE dname)
Definition: file.c:4025
rb_dir_getwd_ospath
VALUE rb_dir_getwd_ospath(void)
Definition: dir.c:1117
rb_str_new2
#define rb_str_new2
Definition: intern.h:903
rb_thread_struct::top_self
VALUE top_self
Definition: vm_core.h:923
rb_ast_struct::body
rb_ast_body_t body
Definition: node.h:402
rb_f_require_relative
VALUE rb_f_require_relative(VALUE obj, VALUE fname)
Definition: load.c:823
rb_f_require
VALUE rb_f_require(VALUE obj, VALUE fname)
Definition: load.c:809
rb_iseq_struct
Definition: vm_core.h:456
IS_SOEXT
#define IS_SOEXT(e)
Definition: load.c:16
rb_gc_register_mark_object
void rb_gc_register_mark_object(VALUE obj)
Definition: gc.c:7063
path
VALUE path
Definition: rb_mjit_min_header-2.7.0.h:7351
EXPAND_HOME
@ EXPAND_HOME
Definition: load.c:34
rb_warn
void rb_warn(const char *fmt,...)
Definition: error.c:313
rb_backtrace_each
void rb_backtrace_each(VALUE(*iter)(VALUE recv, VALUE str), VALUE output)
Definition: vm_backtrace.c:855
imemo_memo
@ imemo_memo
Definition: internal.h:1138
rb_ary_shared_with_p
VALUE rb_ary_shared_with_p(VALUE ary1, VALUE ary2)
Definition: array.c:661
rb_warning
void rb_warning(const char *fmt,...)
Definition: error.c:334
EXPAND_RELATIVE
@ EXPAND_RELATIVE
Definition: load.c:33
rb_ary_free
void rb_ary_free(VALUE ary)
Definition: array.c:786
rb_ary_new_from_args
#define rb_ary_new_from_args(n,...)
Definition: rb_mjit_min_header-2.7.0.h:7214
ST_STOP
@ ST_STOP
Definition: st.h:99
rb_ast_dispose
void rb_ast_dispose(rb_ast_t *ast)
Definition: node.c:1389
rb_scan_args
#define rb_scan_args(argc, argvp, fmt,...)
Definition: rb_mjit_min_header-2.7.0.h:6372
INT2FIX
#define INT2FIX(i)
Definition: ruby.h:263
strchr
char * strchr(char *, char)
st_hash
st_index_t st_hash(const void *ptr, size_t len, st_index_t h)
Definition: st.c:1897
RSTRING_PTR
#define RSTRING_PTR(str)
Definition: ruby.h:1009
rb_thread_struct::top_wrapper
VALUE top_wrapper
Definition: vm_core.h:924
rb_iseq_new_top
rb_iseq_t * rb_iseq_new_top(const rb_ast_body_t *ast, VALUE name, VALUE path, VALUE realpath, const rb_iseq_t *parent)
Definition: iseq.c:769
st_init_numtable
st_table * st_init_numtable(void)
Definition: st.c:653
loaded_feature_searching::load_path
VALUE load_path
Definition: load.c:351
rb_gvar_readonly_setter
void rb_gvar_readonly_setter(VALUE v, ID id, VALUE *_)
Definition: variable.c:412
rb_get_expanded_load_path
VALUE rb_get_expanded_load_path(void)
Definition: load.c:92
VALUE
unsigned long VALUE
Definition: ruby.h:102
rb_scope_visibility_set
void rb_scope_visibility_set(rb_method_visibility_t)
Definition: vm_method.c:1138
index
int index
Definition: rb_mjit_min_header-2.7.0.h:11246
GET_VM
#define GET_VM()
Definition: vm_core.h:1764
rb_module_new
VALUE rb_module_new(void)
Definition: class.c:758
encoding.h
rb_ary_replace
VALUE rb_ary_replace(VALUE copy, VALUE orig)
Definition: array.c:3811
ruby_verbose
#define ruby_verbose
Definition: ruby.h:1925
rb_ary_store
void rb_ary_store(VALUE ary, long idx, VALUE val)
Definition: array.c:1079
RB_TYPE_P
#define RB_TYPE_P(obj, type)
Definition: ruby.h:560
TAG_FATAL
#define TAG_FATAL
Definition: vm_core.h:205
rb_cModule
RUBY_EXTERN VALUE rb_cModule
Definition: ruby.h:2034
int
__inline__ int
Definition: rb_mjit_min_header-2.7.0.h:2839
rb_define_global_function
void rb_define_global_function(const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a global function.
Definition: class.c:1787
EC_JUMP_TAG
#define EC_JUMP_TAG(ec, st)
Definition: eval_intern.h:184
rb_vm_struct::loaded_features
VALUE loaded_features
Definition: vm_core.h:619
StringValue
use StringValue() instead")))
rb_load_protect
void rb_load_protect(VALUE fname, int wrap, int *pstate)
Definition: load.c:657
rb_str_cat2
#define rb_str_cat2
Definition: intern.h:912
Qundef
#define Qundef
Definition: ruby.h:470
rb_define_singleton_method
void rb_define_singleton_method(VALUE obj, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a singleton method for obj.
Definition: class.c:1755
loaded_feature_searching::type
int type
Definition: load.c:350
rb_define_method
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1551
GET_EC
#define GET_EC()
Definition: vm_core.h:1766
feature_func
int(* feature_func)(const char *feature, const char *ext, int rb, int expanded, const char **fn)
Definition: load.c:833
rb_loaderror
void rb_loaderror(const char *fmt,...)
Definition: error.c:2688
Qfalse
#define Qfalse
Definition: ruby.h:467
ruby_sized_xfree
#define ruby_sized_xfree(ptr, size)
Definition: rb_mjit_min_header-2.7.0.h:7367
rb_get_path
VALUE rb_get_path(VALUE obj)
Definition: file.c:230
FilePathValue
#define FilePathValue(v)
Definition: ruby.h:624
rb_vm_struct::expanded_load_path
VALUE expanded_load_path
Definition: vm_core.h:618
loaded_feature_searching::result
const char * result
Definition: load.c:352
SPECIAL_CONST_P
#define SPECIAL_CONST_P(x)
Definition: ruby.h:1313
Init_load
void Init_load(void)
Definition: load.c:1255
rb_parser_load_file
RUBY_SYMBOL_EXPORT_END void * rb_parser_load_file(VALUE parser, VALUE name)
Definition: ruby.c:2193
NULL
#define NULL
Definition: _sdbm.c:101
rb_filesystem_str_new_cstr
VALUE rb_filesystem_str_new_cstr(const char *)
Definition: string.c:1117
rb_check_realpath
VALUE rb_check_realpath(VALUE basedir, VALUE path, rb_encoding *enc)
Definition: file.c:4417
ST_DELETE
@ ST_DELETE
Definition: st.h:99
IS_RBEXT
#define IS_RBEXT(e)
Definition: load.c:15
PRIsVALUE
#define PRIsVALUE
Definition: ruby.h:166
rb_vm_cbase
VALUE rb_vm_cbase(void)
Definition: vm.c:1425
EXPAND_NON_CACHE
@ EXPAND_NON_CACHE
Definition: load.c:35
st_insert
int st_insert(st_table *tab, st_data_t key, st_data_t value)
Definition: st.c:1171
FIX2LONG
#define FIX2LONG(x)
Definition: ruby.h:394
ID2SYM
#define ID2SYM(x)
Definition: ruby.h:414
strlen
size_t strlen(const char *)
OBJ_FREEZE
#define OBJ_FREEZE(x)
Definition: ruby.h:1377
strncmp
int strncmp(const char *, const char *, size_t)
rb_intern
#define rb_intern(str)
rb_autoload_at_p
VALUE rb_autoload_at_p(VALUE, ID, int)
Definition: variable.c:2287
MEMO
MEMO.
Definition: internal.h:1278
rb_check_arity
#define rb_check_arity
Definition: intern.h:347
RUBY_FUNC_EXPORTED
#define RUBY_FUNC_EXPORTED
Definition: defines.h:391
rb_vm_struct::load_path
VALUE load_path
Definition: vm_core.h:615
VM_BLOCK_HANDLER_NONE
#define VM_BLOCK_HANDLER_NONE
Definition: vm_core.h:1291
v
int VALUE v
Definition: rb_mjit_min_header-2.7.0.h:12332
rb_str_resize
VALUE rb_str_resize(VALUE, long)
Definition: string.c:2709
rb_raise
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:2669
MEMO::u3
union MEMO::@109 u3
rb_ary_entry
VALUE rb_ary_entry(VALUE ary, long offset)
Definition: array.c:1512
LONG2NUM
#define LONG2NUM(x)
Definition: ruby.h:1644
obj
const VALUE VALUE obj
Definition: rb_mjit_min_header-2.7.0.h:5742
probes.h
rb_alias_variable
void rb_alias_variable(ID, ID)
Definition: variable.c:756
rb_fstring_cstr
#define rb_fstring_cstr(str)
Definition: rb_mjit_min_header-2.7.0.h:7718
DLEXT_MAXLEN
#define DLEXT_MAXLEN
Definition: defines.h:456
rb_load_fail
void rb_load_fail(VALUE path, const char *err)
Definition: error.c:2965
rb_ast_struct
Definition: node.h:399
rb_thread_shield_new
VALUE rb_thread_shield_new(void)
Definition: thread.c:4790
rb_thread_shield_wait
VALUE rb_thread_shield_wait(VALUE self)
Definition: thread.c:4806
EC_POP_TAG
#define EC_POP_TAG()
Definition: eval_intern.h:137
rb_require_string
VALUE rb_require_string(VALUE fname)
Definition: load.c:1102
rb_setup_fake_str
VALUE rb_setup_fake_str(struct RString *fake_str, const char *name, long len, rb_encoding *enc)
Definition: string.c:385
iseq.h
rb_iseq_load_iseq
const rb_iseq_t * rb_iseq_load_iseq(VALUE fname)
Definition: iseq.c:847
T_FIXNUM
#define T_FIXNUM
Definition: ruby.h:535
rb_ary_cat
VALUE rb_ary_cat(VALUE ary, const VALUE *argv, long len)
Definition: array.c:1208
rb_ary_tmp_new
VALUE rb_ary_tmp_new(long capa)
Definition: array.c:768
i
uint32_t i
Definition: rb_mjit_min_header-2.7.0.h:5464
rb_file_absolute_path
VALUE rb_file_absolute_path(VALUE fname, VALUE dname)
Definition: file.c:4072
rb_vm_top_self
VALUE rb_vm_top_self(void)
Definition: vm.c:3345
sym
#define sym(x)
Definition: date_core.c:3716
st_data_t
RUBY_SYMBOL_EXPORT_BEGIN typedef unsigned long st_data_t
Definition: st.h:22
rb_to_id
ID rb_to_id(VALUE)
Definition: string.c:11146
rb_realpath_internal
VALUE rb_realpath_internal(VALUE basedir, VALUE path, int strict)
Definition: file.c:4409
rb_execution_context_struct::errinfo
VALUE errinfo
Definition: vm_core.h:875
long
#define long
Definition: rb_mjit_min_header-2.7.0.h:2880
rb_file_load_ok
int rb_file_load_ok(const char *path)
Definition: file.c:6222
rb_str_equal
VALUE rb_str_equal(VALUE str1, VALUE str2)
Definition: string.c:3267
rb_ary_push
VALUE rb_ary_push(VALUE ary, VALUE item)
Definition: array.c:1195
rb_vm_struct::load_path_check_cache
VALUE load_path_check_cache
Definition: vm_core.h:617
EC_EXEC_TAG
#define EC_EXEC_TAG()
Definition: eval_intern.h:181
rb_obj_freeze
VALUE rb_obj_freeze(VALUE)
Make the object unmodifiable.
Definition: object.c:1080
EXPAND_ALL
@ EXPAND_ALL
Definition: load.c:32
rb_provided
int rb_provided(const char *feature)
Definition: load.c:513
rb_require_internal
int rb_require_internal(VALUE fname)
Definition: load.c:1067
ruby_init_ext
RUBY_FUNC_EXPORTED void ruby_init_ext(const char *name, void(*init)(void))
Definition: load.c:1139
rb_file_dirname
VALUE rb_file_dirname(VALUE fname)
Definition: file.c:4645
rb_eTypeError
VALUE rb_eTypeError
Definition: error.c:922
rb_require
VALUE rb_require(const char *fname)
Definition: load.c:1118
rb_eRuntimeError
VALUE rb_eRuntimeError
Definition: error.c:920
MEMO_NEW
#define MEMO_NEW(a, b, c)
Definition: internal.h:1296
mod
#define mod(x, y)
Definition: date_strftime.c:28
rb_get_path_check_convert
VALUE rb_get_path_check_convert(VALUE obj)
Definition: file.c:211
RARRAY_AREF
#define RARRAY_AREF(a, i)
Definition: ruby.h:1101
StringValuePtr
#define StringValuePtr(v)
Definition: ruby.h:603
strlcpy
RUBY_EXTERN size_t strlcpy(char *, const char *, size_t)
Definition: strlcpy.c:29
FALSE
#define FALSE
Definition: nkf.h:174
RString
Definition: ruby.h:988
METHOD_VISI_PUBLIC
@ METHOD_VISI_PUBLIC
Definition: method.h:28
rb_thread_shield_destroy
VALUE rb_thread_shield_destroy(VALUE self)
Definition: thread.c:4846
rb_str_new_cstr
#define rb_str_new_cstr(str)
Definition: rb_mjit_min_header-2.7.0.h:6117
RArray
Definition: ruby.h:1048
st_update
int st_update(st_table *tab, st_data_t key, st_update_callback_func *func, st_data_t arg)
Definition: st.c:1510
rb_extend_object
void rb_extend_object(VALUE obj, VALUE module)
Extend the object with the module.
Definition: eval.c:1700
key
key
Definition: openssl_missing.h:181
loaded_feature_searching
Definition: load.c:347
rb_vm_make_jump_tag_but_local_jump
VALUE rb_vm_make_jump_tag_but_local_jump(int state, VALUE val)
Definition: vm.c:1478
TAG_RAISE
#define TAG_RAISE
Definition: vm_core.h:203
RARRAY_LEN
#define RARRAY_LEN(a)
Definition: ruby.h:1070
st_foreach
int st_foreach(st_table *tab, st_foreach_callback_func *func, st_data_t arg)
Definition: st.c:1718
rb_current_realfilepath
VALUE rb_current_realfilepath(void)
Definition: vm_eval.c:2460
buf
unsigned char buf[MIME_BUF_SIZE]
Definition: nkf.c:4322
n
const char size_t n
Definition: rb_mjit_min_header-2.7.0.h:5456
MEMO_CAST
#define MEMO_CAST(m)
Definition: internal.h:1294
rb_exc_raise
void rb_exc_raise(VALUE mesg)
Raises an exception in the current thread.
Definition: eval.c:667
rb_intern2
ID rb_intern2(const char *, long)
Definition: symbol.c:653
rb_str_append
VALUE rb_str_append(VALUE, VALUE)
Definition: string.c:2965
rb_require_safe
VALUE rb_require_safe(VALUE fname, int safe)
Definition: load.c:1085
internal.h
T_ARRAY
#define T_ARRAY
Definition: ruby.h:530
arg
VALUE arg
Definition: rb_mjit_min_header-2.7.0.h:5601
argv
char ** argv
Definition: ruby.c:223
f
#define f
rb_set_errinfo
void rb_set_errinfo(VALUE err)
Sets the current exception ($!) to the given value.
Definition: eval.c:1895
rb_vm_struct::load_path_snapshot
VALUE load_path_snapshot
Definition: vm_core.h:616
ST_CONTINUE
@ ST_CONTINUE
Definition: st.h:99
klass
VALUE klass
Definition: rb_mjit_min_header-2.7.0.h:13254
rb_vm_struct::loaded_features_snapshot
VALUE loaded_features_snapshot
Definition: vm_core.h:620
rb_str_subseq
VALUE rb_str_subseq(VALUE, long, long)
Definition: string.c:2474
st_data_t
unsigned long st_data_t
Definition: rb_mjit_min_header-2.7.0.h:5363
rb_get_path_check_to_string
VALUE rb_get_path_check_to_string(VALUE obj)
Definition: file.c:196
strrchr
char * strrchr(const char *, const char)
str
char str[HTML_ESCAPE_MAX_LEN+1]
Definition: escape.c:18
loaded_feature_searching::len
long len
Definition: load.c:349
MEMCPY
#define MEMCPY(p1, p2, type, n)
Definition: ruby.h:1753
rb_parser_set_context
VALUE rb_parser_set_context(VALUE vparser, const struct rb_iseq_struct *base, int main)
Definition: ripper.c:19234
dln_load
void * dln_load(const char *file)
Definition: dln.c:1261
rb_autoload_str
void rb_autoload_str(VALUE mod, ID id, VALUE file)
Definition: variable.c:1933
rb_str_encode_ospath
VALUE rb_str_encode_ospath(VALUE path)
Definition: file.c:236
NIL_P
#define NIL_P(v)
Definition: ruby.h:482
TAG_NONE
#define TAG_NONE
Definition: vm_core.h:197
rb_warning_string
VALUE rb_warning_string(const char *fmt,...)
Definition: error.c:344
argc
int argc
Definition: ruby.c:222
recur
#define recur(fmt)
Definition: date_strptime.c:152
NORETURN
NORETURN(static void load_failed(VALUE))
rb_vm_call_cfunc
VALUE rb_vm_call_cfunc(VALUE recv, VALUE(*func)(VALUE), VALUE arg, VALUE block_handler, VALUE filename)
Definition: vm.c:2212
rb_vm_struct
Definition: vm_core.h:576
xfree
#define xfree
Definition: defines.h:216
rb_thread_shield_release
VALUE rb_thread_shield_release(VALUE self)
Definition: thread.c:4835
RUBY_DTRACE_HOOK
#define RUBY_DTRACE_HOOK(name, arg)
Definition: internal.h:2586
MEMO::value
const VALUE value
Definition: internal.h:1286
RBASIC
#define RBASIC(obj)
Definition: ruby.h:1267
ruby_strdup
char * ruby_strdup(const char *)
Definition: util.c:527
_
#define _(args)
Definition: dln.h:28
EC_PUSH_TAG
#define EC_PUSH_TAG(ec)
Definition: eval_intern.h:130
Qtrue
#define Qtrue
Definition: ruby.h:468
OBJ_FROZEN
#define OBJ_FROZEN(x)
Definition: ruby.h:1375
len
uint8_t len
Definition: escape.c:17
DLEXT
#define DLEXT
Definition: rb_mjit_min_header-2.7.0.h:435
T_STRING
#define T_STRING
Definition: ruby.h:528
ruby::backward::cxxanyargs::rb_define_hooked_variable
void rb_define_hooked_variable(const char *q, VALUE *w, type *e, void_type *r)
Define a function-backended global variable.
Definition: cxxanyargs.hpp:106
iseq
const rb_iseq_t * iseq
Definition: rb_mjit_min_header-2.7.0.h:13504
rb_is_absolute_path
int rb_is_absolute_path(const char *path)
Definition: file.c:6089
eval_intern.h
rb_provide
void rb_provide(const char *feature)
Definition: load.c:563
ruby_require_internal
int ruby_require_internal(const char *fname, unsigned int len)
Definition: load.c:1074
rb_resolve_feature_path
VALUE rb_resolve_feature_path(VALUE klass, VALUE fname)
Definition: load.c:947
rb_find_file
VALUE rb_find_file(VALUE path)
Definition: file.c:6336
rb_ary_new
VALUE rb_ary_new(void)
Definition: array.c:723
rb_load
void rb_load(VALUE fname, int wrap)
Definition: load.c:649
ruby::backward::cxxanyargs::rb_define_virtual_variable
void rb_define_virtual_variable(const char *q, type *w, void_type *e)
Define a function-backended global variable.
Definition: cxxanyargs.hpp:59
Qnil
#define Qnil
Definition: ruby.h:469
rb_fstring_lit
#define rb_fstring_lit(str)
Definition: internal.h:2123
exc
const rb_iseq_t const VALUE exc
Definition: rb_mjit_min_header-2.7.0.h:13504
st_lookup
int st_lookup(st_table *tab, st_data_t key, st_data_t *value)
Definition: st.c:1101
util.h
rb_find_file_ext
int rb_find_file_ext(VALUE *filep, const char *const *ext)
Definition: file.c:6270
RB_GC_GUARD
#define RB_GC_GUARD(v)
Definition: ruby.h:585
numberof
#define numberof(array)
Definition: etc.c:618
rb_thread_struct
Definition: vm_core.h:910
rb_str_tmp_new
VALUE rb_str_tmp_new(long)
Definition: string.c:1343
MEMO::state
long state
Definition: internal.h:1285
RSTRING_LEN
#define RSTRING_LEN(str)
Definition: ruby.h:1005
st_table
Definition: st.h:79
MEMO::func
void(* func)(void)
Definition: internal.h:1287
ruby_tag_type
ruby_tag_type
Definition: vm_core.h:184
loaded_feature_searching::name
const char * name
Definition: load.c:348
RTEST
#define RTEST(v)
Definition: ruby.h:481
ruby::backward::cxxanyargs::type
VALUE type(ANYARGS)
ANYARGS-ed function type.
Definition: cxxanyargs.hpp:39
TAG_RETURN
#define TAG_RETURN
Definition: vm_core.h:198
rb_obj_clone
VALUE rb_obj_clone(VALUE)
Almost same as Object::clone.
Definition: object.c:410
st_get_key
int st_get_key(st_table *tab, st_data_t key, st_data_t *result)
Definition: st.c:1130
rb_class_real
VALUE rb_class_real(VALUE cl)
Looks up the nearest ancestor of cl, skipping singleton classes or module inclusions.
Definition: object.c:202
dln.h
name
const char * name
Definition: nkf.c:208
rb_execution_context_struct
Definition: vm_core.h:843