Ruby 2.1.5p273(2014-11-13revision48405)

- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

load.c
Go to the documentation of this file.
1 /*
2 * load methods from eval.c
3 */
4
5 #include "ruby/ruby.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 "node.h"
12
13 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 VALUE
32 rb_get_load_path(void)
33 {
34 VALUE load_path = GET_VM()->load_path;
35 return load_path;
36 }
37
38 enum expand_type {
39 EXPAND_ALL,
40 EXPAND_RELATIVE,
41 EXPAND_HOME,
42 EXPAND_NON_CACHE
43 };
44
45 /* Construct expanded load path and store it to cache.
46 We rebuild load path partially if the cache is invalid.
47 We don't cache non string object and expand it every time. We ensure that
48 string objects in $LOAD_PATH are frozen.
49 */
50 static void
51 rb_construct_expanded_load_path(int type, int *has_relative, int *has_non_cache)
52 {
53 rb_vm_t *vm = GET_VM();
54 VALUE load_path = vm->load_path;
55 VALUE expanded_load_path = vm->expanded_load_path;
56 VALUE ary;
57 long i;
58 int level = rb_safe_level();
59
60 ary = rb_ary_tmp_new(RARRAY_LEN(load_path));
61 for (i = 0; i < RARRAY_LEN(load_path); ++i) {
62 VALUE path, as_str, expanded_path;
63 int is_string, non_cache;
64 char *as_cstr;
65 as_str = path = RARRAY_AREF(load_path, i);
66 is_string = RB_TYPE_P(path, T_STRING) ? 1 : 0;
67 non_cache = !is_string ? 1 : 0;
68 as_str = rb_get_path_check_to_string(path, level);
69 as_cstr = RSTRING_PTR(as_str);
70
71 if (!non_cache) {
72 if ((type == EXPAND_RELATIVE &&
73 rb_is_absolute_path(as_cstr)) ||
74 (type == EXPAND_HOME &&
75 (!as_cstr[0] || as_cstr[0] != '~')) ||
76 (type == EXPAND_NON_CACHE)) {
77 /* Use cached expanded path. */
78 rb_ary_push(ary, RARRAY_AREF(expanded_load_path, i));
79 continue;
80 }
81 }
82 if (!*has_relative && !rb_is_absolute_path(as_cstr))
83 *has_relative = 1;
84 if (!*has_non_cache && non_cache)
85 *has_non_cache = 1;
86 /* Freeze only string object. We expand other objects every time. */
87 if (is_string)
88 rb_str_freeze(path);
89 as_str = rb_get_path_check_convert(path, as_str, level);
90 expanded_path = rb_file_expand_path_fast(as_str, Qnil);
91 rb_str_freeze(expanded_path);
92 rb_ary_push(ary, expanded_path);
93 }
94 rb_obj_freeze(ary);
95 vm->expanded_load_path = ary;
96 rb_ary_replace(vm->load_path_snapshot, vm->load_path);
97 }
98
99 static VALUE
100 load_path_getcwd(void)
101 {
102 char *cwd = my_getcwd();
103 VALUE cwd_str = rb_filesystem_str_new_cstr(cwd);
104 xfree(cwd);
105 return cwd_str;
106 }
107
108 VALUE
109 rb_get_expanded_load_path(void)
110 {
111 rb_vm_t *vm = GET_VM();
112 const VALUE non_cache = Qtrue;
113
114 if (!rb_ary_shared_with_p(vm->load_path_snapshot, vm->load_path)) {
115 /* The load path was modified. Rebuild the expanded load path. */
116 int has_relative = 0, has_non_cache = 0;
117 rb_construct_expanded_load_path(EXPAND_ALL, &has_relative, &has_non_cache);
118 if (has_relative) {
119 vm->load_path_check_cache = load_path_getcwd();
120 }
121 else if (has_non_cache) {
122 /* Non string object. */
123 vm->load_path_check_cache = non_cache;
124 }
125 else {
126 vm->load_path_check_cache = 0;
127 }
128 }
129 else if (vm->load_path_check_cache == non_cache) {
130 int has_relative = 1, has_non_cache = 1;
131 /* Expand only non-cacheable objects. */
132 rb_construct_expanded_load_path(EXPAND_NON_CACHE,
133 &has_relative, &has_non_cache);
134 }
135 else if (vm->load_path_check_cache) {
136 int has_relative = 1, has_non_cache = 1;
137 VALUE cwd = load_path_getcwd();
138 if (!rb_str_equal(vm->load_path_check_cache, cwd)) {
139 /* Current working directory or filesystem encoding was changed.
140 Expand relative load path and non-cacheable objects again. */
141 vm->load_path_check_cache = cwd;
142 rb_construct_expanded_load_path(EXPAND_RELATIVE,
143 &has_relative, &has_non_cache);
144 }
145 else {
146 /* Expand only tilde (User HOME) and non-cacheable objects. */
147 rb_construct_expanded_load_path(EXPAND_HOME,
148 &has_relative, &has_non_cache);
149 }
150 }
151 return vm->expanded_load_path;
152 }
153
154 static VALUE
155 load_path_getter(ID id, rb_vm_t *vm)
156 {
157 return vm->load_path;
158 }
159
160 static VALUE
161 get_loaded_features(void)
162 {
163 return GET_VM()->loaded_features;
164 }
165
166 static void
167 reset_loaded_features_snapshot(void)
168 {
169 rb_vm_t *vm = GET_VM();
170 rb_ary_replace(vm->loaded_features_snapshot, vm->loaded_features);
171 }
172
173 static struct st_table *
174 get_loaded_features_index_raw(void)
175 {
176 return GET_VM()->loaded_features_index;
177 }
178
179 static st_table *
180 get_loading_table(void)
181 {
182 return GET_VM()->loading_table;
183 }
184
185 static void
186 features_index_add_single(VALUE short_feature, VALUE offset)
187 {
188 struct st_table *features_index;
189 VALUE this_feature_index = Qnil;
190 char *short_feature_cstr;
191
192 Check_Type(offset, T_FIXNUM);
193 Check_Type(short_feature, T_STRING);
194 short_feature_cstr = StringValueCStr(short_feature);
195
196 features_index = get_loaded_features_index_raw();
197 st_lookup(features_index, (st_data_t)short_feature_cstr, (st_data_t *)&this_feature_index);
198
199 if (NIL_P(this_feature_index)) {
200 st_insert(features_index, (st_data_t)ruby_strdup(short_feature_cstr), (st_data_t)offset);
201 }
202 else if (RB_TYPE_P(this_feature_index, T_FIXNUM)) {
203 VALUE feature_indexes[2];
204 feature_indexes[0] = this_feature_index;
205 feature_indexes[1] = offset;
206 this_feature_index = (VALUE)xcalloc(1, sizeof(struct RArray));
207 RBASIC(this_feature_index)->flags = T_ARRAY; /* fake VALUE, do not mark/sweep */
208 rb_ary_cat(this_feature_index, feature_indexes, numberof(feature_indexes));
209 st_insert(features_index, (st_data_t)short_feature_cstr, (st_data_t)this_feature_index);
210 }
211 else {
212 Check_Type(this_feature_index, T_ARRAY);
213 rb_ary_push(this_feature_index, offset);
214 }
215 }
216
217 /* Add to the loaded-features index all the required entries for
218 `feature`, located at `offset` in $LOADED_FEATURES. We add an
219 index entry at each string `short_feature` for which
220 feature == "#{prefix}#{short_feature}#{e}"
221 where `e` is empty or matches %r{^\.[^./]*$}, and `prefix` is empty
222 or ends in '/'. This maintains the invariant that `rb_feature_p()`
223 relies on for its fast lookup.
224 */
225 static void
226 features_index_add(VALUE feature, VALUE offset)
227 {
228 VALUE short_feature;
229 const char *feature_str, *feature_end, *ext, *p;
230
231 feature_str = StringValuePtr(feature);
232 feature_end = feature_str + RSTRING_LEN(feature);
233
234 for (ext = feature_end; ext > feature_str; ext--)
235 if (*ext == '.' || *ext == '/')
236 break;
237 if (*ext != '.')
238 ext = NULL;
239 /* Now `ext` points to the only string matching %r{^\.[^./]*$} that is
240 at the end of `feature`, or is NULL if there is no such string. */
241
242 p = ext ? ext : feature_end;
243 while (1) {
244 p--;
245 while (p >= feature_str && *p != '/')
246 p--;
247 if (p < feature_str)
248 break;
249 /* Now *p == '/'. We reach this point for every '/' in `feature`. */
250 short_feature = rb_str_subseq(feature, p + 1 - feature_str, feature_end - p - 1);
251 features_index_add_single(short_feature, offset);
252 if (ext) {
253 short_feature = rb_str_subseq(feature, p + 1 - feature_str, ext - p - 1);
254 features_index_add_single(short_feature, offset);
255 }
256 }
257 features_index_add_single(feature, offset);
258 if (ext) {
259 short_feature = rb_str_subseq(feature, 0, ext - feature_str);
260 features_index_add_single(short_feature, offset);
261 }
262 }
263
264 static int
265 loaded_features_index_clear_i(st_data_t key, st_data_t val, st_data_t arg)
266 {
267 VALUE obj = (VALUE)val;
268 if (!SPECIAL_CONST_P(obj)) {
269 rb_ary_free(obj);
270 xfree((void *)obj);
271 }
272 xfree((char *)key);
273 return ST_DELETE;
274 }
275
276 static st_table *
277 get_loaded_features_index(void)
278 {
279 VALUE features;
280 int i;
281 rb_vm_t *vm = GET_VM();
282
283 if (!rb_ary_shared_with_p(vm->loaded_features_snapshot, vm->loaded_features)) {
284 /* The sharing was broken; something (other than us in rb_provide_feature())
285 modified loaded_features. Rebuild the index. */
286 st_foreach(vm->loaded_features_index, loaded_features_index_clear_i, 0);
287 features = vm->loaded_features;
288 for (i = 0; i < RARRAY_LEN(features); i++) {
289 VALUE entry, as_str;
290 as_str = entry = rb_ary_entry(features, i);
291 StringValue(as_str);
292 if (as_str != entry)
293 rb_ary_store(features, i, as_str);
294 rb_str_freeze(as_str);
295 features_index_add(as_str, INT2FIX(i));
296 }
297 reset_loaded_features_snapshot();
298 }
299 return vm->loaded_features_index;
300 }
301
302 /* This searches `load_path` for a value such that
303 name == "#{load_path[i]}/#{feature}"
304 if `feature` is a suffix of `name`, or otherwise
305 name == "#{load_path[i]}/#{feature}#{ext}"
306 for an acceptable string `ext`. It returns
307 `load_path[i].to_str` if found, else 0.
308
309 If type is 's', then `ext` is acceptable only if IS_DLEXT(ext);
310 if 'r', then only if IS_RBEXT(ext); otherwise `ext` may be absent
311 or have any value matching `%r{^\.[^./]*$}`.
312 */
313 static VALUE
314 loaded_feature_path(const char *name, long vlen, const char *feature, long len,
315 int type, VALUE load_path)
316 {
317 long i;
318 long plen;
319 const char *e;
320
321 if (vlen < len+1) return 0;
322 if (!strncmp(name+(vlen-len), feature, len)) {
323 plen = vlen - len;
324 }
325 else {
326 for (e = name + vlen; name != e && *e != '.' && *e != '/'; --e);
327 if (*e != '.' ||
328 e-name < len ||
329 strncmp(e-len, feature, len))
330 return 0;
331 plen = e - name - len;
332 }
333 if (plen > 0 && name[plen-1] != '/') {
334 return 0;
335 }
336 if (type == 's' ? !IS_DLEXT(&name[plen+len]) :
337 type == 'r' ? !IS_RBEXT(&name[plen+len]) :
338 0) {
339 return 0;
340 }
341 /* Now name == "#{prefix}/#{feature}#{ext}" where ext is acceptable
342 (possibly empty) and prefix is some string of length plen. */
343
344 if (plen > 0) --plen; /* exclude '.' */
345 for (i = 0; i < RARRAY_LEN(load_path); ++i) {
346 VALUE p = RARRAY_AREF(load_path, i);
347 const char *s = StringValuePtr(p);
348 long n = RSTRING_LEN(p);
349
350 if (n != plen) continue;
351 if (n && strncmp(name, s, n)) continue;
352 return p;
353 }
354 return 0;
355 }
356
357 struct loaded_feature_searching {
358 const char *name;
359 long len;
360 int type;
361 VALUE load_path;
362 const char *result;
363 };
364
365 static int
366 loaded_feature_path_i(st_data_t v, st_data_t b, st_data_t f)
367 {
368 const char *s = (const char *)v;
369 struct loaded_feature_searching *fp = (struct loaded_feature_searching *)f;
370 VALUE p = loaded_feature_path(s, strlen(s), fp->name, fp->len,
371 fp->type, fp->load_path);
372 if (!p) return ST_CONTINUE;
373 fp->result = s;
374 return ST_STOP;
375 }
376
377 static int
378 rb_feature_p(const char *feature, const char *ext, int rb, int expanded, const char **fn)
379 {
380 VALUE features, this_feature_index = Qnil, v, p, load_path = 0;
381 const char *f, *e;
382 long i, len, elen, n;
383 st_table *loading_tbl, *features_index;
384 st_data_t data;
385 int type;
386
387 if (fn) *fn = 0;
388 if (ext) {
389 elen = strlen(ext);
390 len = strlen(feature) - elen;
391 type = rb ? 'r' : 's';
392 }
393 else {
394 len = strlen(feature);
395 elen = 0;
396 type = 0;
397 }
398 features = get_loaded_features();
399 features_index = get_loaded_features_index();
400
401 st_lookup(features_index, (st_data_t)feature, (st_data_t *)&this_feature_index);
402 /* We search `features` for an entry such that either
403 "#{features[i]}" == "#{load_path[j]}/#{feature}#{e}"
404 for some j, or
405 "#{features[i]}" == "#{feature}#{e}"
406 Here `e` is an "allowed" extension -- either empty or one
407 of the extensions accepted by IS_RBEXT, IS_SOEXT, or
408 IS_DLEXT. Further, if `ext && rb` then `IS_RBEXT(e)`,
409 and if `ext && !rb` then `IS_SOEXT(e) || IS_DLEXT(e)`.
410
411 If `expanded`, then only the latter form (without load_path[j])
412 is accepted. Otherwise either form is accepted, *unless* `ext`
413 is false and an otherwise-matching entry of the first form is
414 preceded by an entry of the form
415 "#{features[i2]}" == "#{load_path[j2]}/#{feature}#{e2}"
416 where `e2` matches %r{^\.[^./]*$} but is not an allowed extension.
417 After a "distractor" entry of this form, only entries of the
418 form "#{feature}#{e}" are accepted.
419
420 In `rb_provide_feature()` and `get_loaded_features_index()` we
421 maintain an invariant that the array `this_feature_index` will
422 point to every entry in `features` which has the form
423 "#{prefix}#{feature}#{e}"
424 where `e` is empty or matches %r{^\.[^./]*$}, and `prefix` is empty
425 or ends in '/'. This includes both match forms above, as well
426 as any distractors, so we may ignore all other entries in `features`.
427 */
428 if (!NIL_P(this_feature_index)) {
429 for (i = 0; ; i++) {
430 VALUE entry;
431 long index;
432 if (RB_TYPE_P(this_feature_index, T_ARRAY)) {
433 if (i >= RARRAY_LEN(this_feature_index)) break;
434 entry = RARRAY_AREF(this_feature_index, i);
435 }
436 else {
437 if (i > 0) break;
438 entry = this_feature_index;
439 }
440 index = FIX2LONG(entry);
441
442 v = RARRAY_AREF(features, index);
443 f = StringValuePtr(v);
444 if ((n = RSTRING_LEN(v)) < len) continue;
445 if (strncmp(f, feature, len) != 0) {
446 if (expanded) continue;
447 if (!load_path) load_path = rb_get_expanded_load_path();
448 if (!(p = loaded_feature_path(f, n, feature, len, type, load_path)))
449 continue;
450 expanded = 1;
451 f += RSTRING_LEN(p) + 1;
452 }
453 if (!*(e = f + len)) {
454 if (ext) continue;
455 return 'u';
456 }
457 if (*e != '.') continue;
458 if ((!rb || !ext) && (IS_SOEXT(e) || IS_DLEXT(e))) {
459 return 's';
460 }
461 if ((rb || !ext) && (IS_RBEXT(e))) {
462 return 'r';
463 }
464 }
465 }
466
467 loading_tbl = get_loading_table();
468 if (loading_tbl) {
469 f = 0;
470 if (!expanded) {
471 struct loaded_feature_searching fs;
472 fs.name = feature;
473 fs.len = len;
474 fs.type = type;
475 fs.load_path = load_path ? load_path : rb_get_expanded_load_path();
476 fs.result = 0;
477 st_foreach(loading_tbl, loaded_feature_path_i, (st_data_t)&fs);
478 if ((f = fs.result) != 0) {
479 if (fn) *fn = f;
480 goto loading;
481 }
482 }
483 if (st_get_key(loading_tbl, (st_data_t)feature, &data)) {
484 if (fn) *fn = (const char*)data;
485 loading:
486 if (!ext) return 'u';
487 return !IS_RBEXT(ext) ? 's' : 'r';
488 }
489 else {
490 VALUE bufstr;
491 char *buf;
492 static const char so_ext[][4] = {
493 ".so", ".o",
494 };
495
496 if (ext && *ext) return 0;
497 bufstr = rb_str_tmp_new(len + DLEXT_MAXLEN);
498 buf = RSTRING_PTR(bufstr);
499 MEMCPY(buf, feature, char, len);
500 for (i = 0; (e = loadable_ext[i]) != 0; i++) {
501 strlcpy(buf + len, e, DLEXT_MAXLEN + 1);
502 if (st_get_key(loading_tbl, (st_data_t)buf, &data)) {
503 rb_str_resize(bufstr, 0);
504 if (fn) *fn = (const char*)data;
505 return i ? 's' : 'r';
506 }
507 }
508 for (i = 0; i < numberof(so_ext); i++) {
509 strlcpy(buf + len, so_ext[i], DLEXT_MAXLEN + 1);
510 if (st_get_key(loading_tbl, (st_data_t)buf, &data)) {
511 rb_str_resize(bufstr, 0);
512 if (fn) *fn = (const char*)data;
513 return 's';
514 }
515 }
516 rb_str_resize(bufstr, 0);
517 }
518 }
519 return 0;
520 }
521
522 int
523 rb_provided(const char *feature)
524 {
525 return rb_feature_provided(feature, 0);
526 }
527
528 int
529 rb_feature_provided(const char *feature, const char **loading)
530 {
531 const char *ext = strrchr(feature, '.');
532 volatile VALUE fullpath = 0;
533
534 if (*feature == '.' &&
535 (feature[1] == '/' || strncmp(feature+1, "./", 2) == 0)) {
536 fullpath = rb_file_expand_path_fast(rb_get_path(rb_str_new2(feature)), Qnil);
537 feature = RSTRING_PTR(fullpath);
538 }
539 if (ext && !strchr(ext, '/')) {
540 if (IS_RBEXT(ext)) {
541 if (rb_feature_p(feature, ext, TRUE, FALSE, loading)) return TRUE;
542 return FALSE;
543 }
544 else if (IS_SOEXT(ext) || IS_DLEXT(ext)) {
545 if (rb_feature_p(feature, ext, FALSE, FALSE, loading)) return TRUE;
546 return FALSE;
547 }
548 }
549 if (rb_feature_p(feature, 0, TRUE, FALSE, loading))
550 return TRUE;
551 return FALSE;
552 }
553
554 static void
555 rb_provide_feature(VALUE feature)
556 {
557 VALUE features;
558
559 features = get_loaded_features();
560 if (OBJ_FROZEN(features)) {
561 rb_raise(rb_eRuntimeError,
562 "$LOADED_FEATURES is frozen; cannot append feature");
563 }
564 rb_str_freeze(feature);
565
566 rb_ary_push(features, feature);
567 features_index_add(feature, INT2FIX(RARRAY_LEN(features)-1));
568 reset_loaded_features_snapshot();
569 }
570
571 void
572 rb_provide(const char *feature)
573 {
574 rb_provide_feature(rb_usascii_str_new2(feature));
575 }
576
577 NORETURN(static void load_failed(VALUE));
578
579 static inline void
580 rb_load_internal0(rb_thread_t *th, VALUE fname, int wrap)
581 {
582 int state;
583 volatile VALUE wrapper = th->top_wrapper;
584 volatile VALUE self = th->top_self;
585 volatile int loaded = FALSE;
586 volatile int mild_compile_error;
587 #if !defined __GNUC__
588 rb_thread_t *volatile th0 = th;
589 #endif
590
591 th->errinfo = Qnil; /* ensure */
592
593 if (!wrap) {
594 th->top_wrapper = 0;
595 }
596 else {
597 /* load in anonymous module as toplevel */
598 th->top_self = rb_obj_clone(rb_vm_top_self());
599 th->top_wrapper = rb_module_new();
600 rb_extend_object(th->top_self, th->top_wrapper);
601 }
602
603 mild_compile_error = th->mild_compile_error;
604 PUSH_TAG();
605 state = EXEC_TAG();
606 if (state == 0) {
607 NODE *node;
608 VALUE iseq;
609
610 th->mild_compile_error++;
611 node = (NODE *)rb_load_file_str(fname);
612 loaded = TRUE;
613 iseq = rb_iseq_new_top(node, rb_str_new2("<top (required)>"), fname, rb_realpath_internal(Qnil, fname, 1), Qfalse);
614 th->mild_compile_error--;
615 rb_iseq_eval(iseq);
616 }
617 POP_TAG();
618
619 #if !defined __GNUC__
620 th = th0;
621 fname = RB_GC_GUARD(fname);
622 #endif
623 th->mild_compile_error = mild_compile_error;
624 th->top_self = self;
625 th->top_wrapper = wrapper;
626
627 if (!loaded && !FIXNUM_P(th->errinfo)) {
628 /* an error on loading don't include INT2FIX(TAG_FATAL) see r35625 */
629 rb_exc_raise(th->errinfo);
630 }
631 if (state) {
632 rb_vm_jump_tag_but_local_jump(state);
633 }
634
635 if (!NIL_P(th->errinfo)) {
636 /* exception during load */
637 rb_exc_raise(th->errinfo);
638 }
639 }
640
641 static void
642 rb_load_internal(VALUE fname, int wrap)
643 {
644 rb_load_internal0(GET_THREAD(), fname, wrap);
645 }
646
647 void
648 rb_load(VALUE fname, int wrap)
649 {
650 VALUE tmp = rb_find_file(FilePathValue(fname));
651 if (!tmp) load_failed(fname);
652 rb_load_internal(tmp, wrap);
653 }
654
655 void
656 rb_load_protect(VALUE fname, int wrap, int *state)
657 {
658 int status;
659
660 PUSH_TAG();
661 if ((status = EXEC_TAG()) == 0) {
662 rb_load(fname, wrap);
663 }
664 POP_TAG();
665 if (state)
666 *state = status;
667 }
668
669 /*
670 * call-seq:
671 * load(filename, wrap=false) -> true
672 *
673 * Loads and executes the Ruby
674 * program in the file _filename_. If the filename does not
675 * resolve to an absolute path, the file is searched for in the library
676 * directories listed in <code>$:</code>. If the optional _wrap_
677 * parameter is +true+, the loaded script will be executed
678 * under an anonymous module, protecting the calling program's global
679 * namespace. In no circumstance will any local variables in the loaded
680 * file be propagated to the loading environment.
681 */
682
683 static VALUE
684 rb_f_load(int argc, VALUE *argv)
685 {
686 VALUE fname, wrap, path;
687
688 rb_scan_args(argc, argv, "11", &fname, &wrap);
689
690 if (RUBY_DTRACE_LOAD_ENTRY_ENABLED()) {
691 RUBY_DTRACE_LOAD_ENTRY(StringValuePtr(fname),
692 rb_sourcefile(),
693 rb_sourceline());
694 }
695
696 path = rb_find_file(FilePathValue(fname));
697 if (!path) {
698 if (!rb_file_load_ok(RSTRING_PTR(fname)))
699 load_failed(fname);
700 path = fname;
701 }
702 rb_load_internal(path, RTEST(wrap));
703
704 if (RUBY_DTRACE_LOAD_RETURN_ENABLED()) {
705 RUBY_DTRACE_LOAD_RETURN(StringValuePtr(fname),
706 rb_sourcefile(),
707 rb_sourceline());
708 }
709
710 return Qtrue;
711 }
712
713 static char *
714 load_lock(const char *ftptr)
715 {
716 st_data_t data;
717 st_table *loading_tbl = get_loading_table();
718
719 if (!loading_tbl || !st_lookup(loading_tbl, (st_data_t)ftptr, &data)) {
720 /* loading ruby library should be serialized. */
721 if (!loading_tbl) {
722 GET_VM()->loading_table = loading_tbl = st_init_strtable();
723 }
724 /* partial state */
725 ftptr = ruby_strdup(ftptr);
726 data = (st_data_t)rb_thread_shield_new();
727 st_insert(loading_tbl, (st_data_t)ftptr, data);
728 return (char *)ftptr;
729 }
730 else if (RB_TYPE_P((VALUE)data, T_NODE) && nd_type((VALUE)data) == NODE_MEMO) {
731 NODE *memo = RNODE(data);
732 void (*init)(void) = (void (*)(void))memo->nd_cfnc;
733 data = (st_data_t)rb_thread_shield_new();
734 st_insert(loading_tbl, (st_data_t)ftptr, data);
735 (*init)();
736 return (char *)"";
737 }
738 if (RTEST(ruby_verbose)) {
739 rb_warning("loading in progress, circular require considered harmful - %s", ftptr);
740 rb_backtrace_print_to(rb_stderr);
741 }
742 switch (rb_thread_shield_wait((VALUE)data)) {
743 case Qfalse:
744 data = (st_data_t)ftptr;
745 st_insert(loading_tbl, data, (st_data_t)rb_thread_shield_new());
746 return 0;
747 case Qnil:
748 return 0;
749 }
750 return (char *)ftptr;
751 }
752
753 static int
754 release_thread_shield(st_data_t *key, st_data_t *value, st_data_t done, int existing)
755 {
756 VALUE thread_shield = (VALUE)*value;
757 if (!existing) return ST_STOP;
758 if (done ? rb_thread_shield_destroy(thread_shield) : rb_thread_shield_release(thread_shield)) {
759 /* still in-use */
760 return ST_CONTINUE;
761 }
762 xfree((char *)*key);
763 return ST_DELETE;
764 }
765
766 static void
767 load_unlock(const char *ftptr, int done)
768 {
769 if (ftptr) {
770 st_data_t key = (st_data_t)ftptr;
771 st_table *loading_tbl = get_loading_table();
772
773 st_update(loading_tbl, key, release_thread_shield, done);
774 }
775 }
776
777
778 /*
779 * call-seq:
780 * require(name) -> true or false
781 *
782 * Loads the given +name+, returning +true+ if successful and +false+ if the
783 * feature is already loaded.
784 *
785 * If the filename does not resolve to an absolute path, it will be searched
786 * for in the directories listed in <code>$LOAD_PATH</code> (<code>$:</code>).
787 *
788 * If the filename has the extension ".rb", it is loaded as a source file; if
789 * the extension is ".so", ".o", or ".dll", or the default shared library
790 * extension on the current platform, Ruby loads the shared library as a
791 * Ruby extension. Otherwise, Ruby tries adding ".rb", ".so", and so on
792 * to the name until found. If the file named cannot be found, a LoadError
793 * will be raised.
794 *
795 * For Ruby extensions the filename given may use any shared library
796 * extension. For example, on Linux the socket extension is "socket.so" and
797 * <code>require 'socket.dll'</code> will load the socket extension.
798 *
799 * The absolute path of the loaded file is added to
800 * <code>$LOADED_FEATURES</code> (<code>$"</code>). A file will not be
801 * loaded again if its path already appears in <code>$"</code>. For example,
802 * <code>require 'a'; require './a'</code> will not load <code>a.rb</code>
803 * again.
804 *
805 * require "my-library.rb"
806 * require "db-driver"
807 *
808 * Any constants or globals within the loaded source file will be available
809 * in the calling program's global namespace. However, local variables will
810 * not be propagated to the loading environment.
811 *
812 */
813
814 VALUE
815 rb_f_require(VALUE obj, VALUE fname)
816 {
817 return rb_require_safe(fname, rb_safe_level());
818 }
819
820 /*
821 * call-seq:
822 * require_relative(string) -> true or false
823 *
824 * Ruby tries to load the library named _string_ relative to the requiring
825 * file's path. If the file's path cannot be determined a LoadError is raised.
826 * If a file is loaded +true+ is returned and false otherwise.
827 */
828 VALUE
829 rb_f_require_relative(VALUE obj, VALUE fname)
830 {
831 VALUE base = rb_current_realfilepath();
832 if (NIL_P(base)) {
833 rb_loaderror("cannot infer basepath");
834 }
835 base = rb_file_dirname(base);
836 return rb_require_safe(rb_file_absolute_path(fname, base), rb_safe_level());
837 }
838
839 static int
840 search_required(VALUE fname, volatile VALUE *path, int safe_level)
841 {
842 VALUE tmp;
843 char *ext, *ftptr;
844 int type, ft = 0;
845 const char *loading;
846
847 *path = 0;
848 ext = strrchr(ftptr = RSTRING_PTR(fname), '.');
849 if (ext && !strchr(ext, '/')) {
850 if (IS_RBEXT(ext)) {
851 if (rb_feature_p(ftptr, ext, TRUE, FALSE, &loading)) {
852 if (loading) *path = rb_filesystem_str_new_cstr(loading);
853 return 'r';
854 }
855 if ((tmp = rb_find_file_safe(fname, safe_level)) != 0) {
856 ext = strrchr(ftptr = RSTRING_PTR(tmp), '.');
857 if (!rb_feature_p(ftptr, ext, TRUE, TRUE, &loading) || loading)
858 *path = tmp;
859 return 'r';
860 }
861 return 0;
862 }
863 else if (IS_SOEXT(ext)) {
864 if (rb_feature_p(ftptr, ext, FALSE, FALSE, &loading)) {
865 if (loading) *path = rb_filesystem_str_new_cstr(loading);
866 return 's';
867 }
868 tmp = rb_str_subseq(fname, 0, ext - RSTRING_PTR(fname));
869 #ifdef DLEXT2
870 OBJ_FREEZE(tmp);
871 if (rb_find_file_ext_safe(&tmp, loadable_ext + 1, safe_level)) {
872 ext = strrchr(ftptr = RSTRING_PTR(tmp), '.');
873 if (!rb_feature_p(ftptr, ext, FALSE, TRUE, &loading) || loading)
874 *path = tmp;
875 return 's';
876 }
877 #else
878 rb_str_cat2(tmp, DLEXT);
879 OBJ_FREEZE(tmp);
880 if ((tmp = rb_find_file_safe(tmp, safe_level)) != 0) {
881 ext = strrchr(ftptr = RSTRING_PTR(tmp), '.');
882 if (!rb_feature_p(ftptr, ext, FALSE, TRUE, &loading) || loading)
883 *path = tmp;
884 return 's';
885 }
886 #endif
887 }
888 else if (IS_DLEXT(ext)) {
889 if (rb_feature_p(ftptr, ext, FALSE, FALSE, &loading)) {
890 if (loading) *path = rb_filesystem_str_new_cstr(loading);
891 return 's';
892 }
893 if ((tmp = rb_find_file_safe(fname, safe_level)) != 0) {
894 ext = strrchr(ftptr = RSTRING_PTR(tmp), '.');
895 if (!rb_feature_p(ftptr, ext, FALSE, TRUE, &loading) || loading)
896 *path = tmp;
897 return 's';
898 }
899 }
900 }
901 else if ((ft = rb_feature_p(ftptr, 0, FALSE, FALSE, &loading)) == 'r') {
902 if (loading) *path = rb_filesystem_str_new_cstr(loading);
903 return 'r';
904 }
905 tmp = fname;
906 type = rb_find_file_ext_safe(&tmp, loadable_ext, safe_level);
907 switch (type) {
908 case 0:
909 if (ft)
910 goto statically_linked;
911 ftptr = RSTRING_PTR(tmp);
912 return rb_feature_p(ftptr, 0, FALSE, TRUE, 0);
913
914 default:
915 if (ft) {
916 statically_linked:
917 if (loading) *path = rb_filesystem_str_new_cstr(loading);
918 return ft;
919 }
920 case 1:
921 ext = strrchr(ftptr = RSTRING_PTR(tmp), '.');
922 if (rb_feature_p(ftptr, ext, !--type, TRUE, &loading) && !loading)
923 break;
924 *path = tmp;
925 }
926 return type ? 's' : 'r';
927 }
928
929 static void
930 load_failed(VALUE fname)
931 {
932 rb_load_fail(fname, "cannot load such file");
933 }
934
935 static VALUE
936 load_ext(VALUE path)
937 {
938 SCOPE_SET(NOEX_PUBLIC);
939 return (VALUE)dln_load(RSTRING_PTR(path));
940 }
941
942 VALUE
943 rb_require_safe(VALUE fname, int safe)
944 {
945 volatile VALUE result = Qnil;
946 rb_thread_t *th = GET_THREAD();
947 volatile VALUE errinfo = th->errinfo;
948 int state;
949 struct {
950 int safe;
951 } volatile saved;
952 char *volatile ftptr = 0;
953
954 if (RUBY_DTRACE_REQUIRE_ENTRY_ENABLED()) {
955 RUBY_DTRACE_REQUIRE_ENTRY(StringValuePtr(fname),
956 rb_sourcefile(),
957 rb_sourceline());
958 }
959
960 PUSH_TAG();
961 saved.safe = rb_safe_level();
962 if ((state = EXEC_TAG()) == 0) {
963 VALUE path;
964 long handle;
965 int found;
966
967 rb_set_safe_level_force(safe);
968 FilePathValue(fname);
969 rb_set_safe_level_force(0);
970
971 if (RUBY_DTRACE_FIND_REQUIRE_ENTRY_ENABLED()) {
972 RUBY_DTRACE_FIND_REQUIRE_ENTRY(StringValuePtr(fname),
973 rb_sourcefile(),
974 rb_sourceline());
975 }
976
977 path = rb_str_encode_ospath(fname);
978 found = search_required(path, &path, safe);
979
980 if (RUBY_DTRACE_FIND_REQUIRE_RETURN_ENABLED()) {
981 RUBY_DTRACE_FIND_REQUIRE_RETURN(StringValuePtr(fname),
982 rb_sourcefile(),
983 rb_sourceline());
984 }
985 if (found) {
986 if (!path || !(ftptr = load_lock(RSTRING_PTR(path)))) {
987 result = Qfalse;
988 }
989 else if (!*ftptr) {
990 rb_provide_feature(path);
991 result = Qtrue;
992 }
993 else {
994 switch (found) {
995 case 'r':
996 rb_load_internal(path, 0);
997 break;
998
999 case 's':
1000 handle = (long)rb_vm_call_cfunc(rb_vm_top_self(), load_ext,
1001 path, 0, path);
1002 rb_ary_push(ruby_dln_librefs, LONG2NUM(handle));
1003 break;
1004 }
1005 rb_provide_feature(path);
1006 result = Qtrue;
1007 }
1008 }
1009 }
1010 POP_TAG();
1011 load_unlock(ftptr, !state);
1012
1013 rb_set_safe_level_force(saved.safe);
1014 if (state) {
1015 JUMP_TAG(state);
1016 }
1017
1018 if (NIL_P(result)) {
1019 load_failed(fname);
1020 }
1021
1022 th->errinfo = errinfo;
1023
1024 if (RUBY_DTRACE_REQUIRE_RETURN_ENABLED()) {
1025 RUBY_DTRACE_REQUIRE_RETURN(StringValuePtr(fname),
1026 rb_sourcefile(),
1027 rb_sourceline());
1028 }
1029
1030 return result;
1031 }
1032
1033 VALUE
1034 rb_require(const char *fname)
1035 {
1036 VALUE fn = rb_str_new2(fname);
1037 OBJ_FREEZE(fn);
1038 return rb_require_safe(fn, rb_safe_level());
1039 }
1040
1041 static int
1042 register_init_ext(st_data_t *key, st_data_t *value, st_data_t init, int existing)
1043 {
1044 const char *name = (char *)*key;
1045 if (existing) {
1046 /* already registered */
1047 rb_warn("%s is already registered", name);
1048 }
1049 else {
1050 *value = (st_data_t)NEW_MEMO(init, 0, 0);
1051 *key = (st_data_t)ruby_strdup(name);
1052 }
1053 return ST_CONTINUE;
1054 }
1055
1056 RUBY_FUNC_EXPORTED void
1057 ruby_init_ext(const char *name, void (*init)(void))
1058 {
1059 st_table *loading_tbl = get_loading_table();
1060
1061 if (!loading_tbl) {
1062 GET_VM()->loading_table = loading_tbl = st_init_strtable();
1063 }
1064 st_update(loading_tbl, (st_data_t)name, register_init_ext, (st_data_t)init);
1065 }
1066
1067 /*
1068 * call-seq:
1069 * mod.autoload(module, filename) -> nil
1070 *
1071 * Registers _filename_ to be loaded (using <code>Kernel::require</code>)
1072 * the first time that _module_ (which may be a <code>String</code> or
1073 * a symbol) is accessed in the namespace of _mod_.
1074 *
1075 * module A
1076 * end
1077 * A.autoload(:B, "b")
1078 * A::B.doit # autoloads "b"
1079 */
1080
1081 static VALUE
1082 rb_mod_autoload(VALUE mod, VALUE sym, VALUE file)
1083 {
1084 ID id = rb_to_id(sym);
1085
1086 FilePathValue(file);
1087 rb_autoload(mod, id, RSTRING_PTR(file));
1088 return Qnil;
1089 }
1090
1091 /*
1092 * call-seq:
1093 * mod.autoload?(name) -> String or nil
1094 *
1095 * Returns _filename_ to be loaded if _name_ is registered as
1096 * +autoload+ in the namespace of _mod_.
1097 *
1098 * module A
1099 * end
1100 * A.autoload(:B, "b")
1101 * A.autoload?(:B) #=> "b"
1102 */
1103
1104 static VALUE
1105 rb_mod_autoload_p(VALUE mod, VALUE sym)
1106 {
1107 ID id = rb_check_id(&sym);
1108 if (!id) {
1109 return Qnil;
1110 }
1111 return rb_autoload_p(mod, id);
1112 }
1113
1114 /*
1115 * call-seq:
1116 * autoload(module, filename) -> nil
1117 *
1118 * Registers _filename_ to be loaded (using <code>Kernel::require</code>)
1119 * the first time that _module_ (which may be a <code>String</code> or
1120 * a symbol) is accessed.
1121 *
1122 * autoload(:MyModule, "/usr/local/lib/modules/my_module.rb")
1123 */
1124
1125 static VALUE
1126 rb_f_autoload(VALUE obj, VALUE sym, VALUE file)
1127 {
1128 VALUE klass = rb_class_real(rb_vm_cbase());
1129 if (NIL_P(klass)) {
1130 rb_raise(rb_eTypeError, "Can not set autoload on singleton class");
1131 }
1132 return rb_mod_autoload(klass, sym, file);
1133 }
1134
1135 /*
1136 * call-seq:
1137 * autoload?(name) -> String or nil
1138 *
1139 * Returns _filename_ to be loaded if _name_ is registered as
1140 * +autoload+.
1141 *
1142 * autoload(:B, "b")
1143 * autoload?(:B) #=> "b"
1144 */
1145
1146 static VALUE
1147 rb_f_autoload_p(VALUE obj, VALUE sym)
1148 {
1149 /* use rb_vm_cbase() as same as rb_f_autoload. */
1150 VALUE klass = rb_vm_cbase();
1151 if (NIL_P(klass)) {
1152 return Qnil;
1153 }
1154 return rb_mod_autoload_p(klass, sym);
1155 }
1156
1157 void
1158 Init_load()
1159 {
1160 #undef rb_intern
1161 #define rb_intern(str) rb_intern2((str), strlen(str))
1162 rb_vm_t *vm = GET_VM();
1163 static const char var_load_path[] = "$:";
1164 ID id_load_path = rb_intern2(var_load_path, sizeof(var_load_path)-1);
1165
1166 rb_define_hooked_variable(var_load_path, (VALUE*)vm, load_path_getter, rb_gvar_readonly_setter);
1167 rb_alias_variable(rb_intern("$-I"), id_load_path);
1168 rb_alias_variable(rb_intern("$LOAD_PATH"), id_load_path);
1169 vm->load_path = rb_ary_new();
1170 vm->expanded_load_path = rb_ary_tmp_new(0);
1171 vm->load_path_snapshot = rb_ary_tmp_new(0);
1172 vm->load_path_check_cache = 0;
1173
1174 rb_define_virtual_variable("$\"", get_loaded_features, 0);
1175 rb_define_virtual_variable("$LOADED_FEATURES", get_loaded_features, 0);
1176 vm->loaded_features = rb_ary_new();
1177 vm->loaded_features_snapshot = rb_ary_tmp_new(0);
1178 vm->loaded_features_index = st_init_strtable();
1179
1180 rb_define_global_function("load", rb_f_load, -1);
1181 rb_define_global_function("require", rb_f_require, 1);
1182 rb_define_global_function("require_relative", rb_f_require_relative, 1);
1183 rb_define_method(rb_cModule, "autoload", rb_mod_autoload, 2);
1184 rb_define_method(rb_cModule, "autoload?", rb_mod_autoload_p, 1);
1185 rb_define_global_function("autoload", rb_f_autoload, 2);
1186 rb_define_global_function("autoload?", rb_f_autoload_p, 1);
1187
1188 ruby_dln_librefs = rb_ary_tmp_new(0);
1189 rb_gc_register_mark_object(ruby_dln_librefs);
1190 }
ruby_dln_librefs
VALUE ruby_dln_librefs
Definition: load.c:13
rb_backtrace_print_to
void rb_backtrace_print_to(VALUE output)
Definition: vm_backtrace.c:803
rb_get_path_check_convert
VALUE rb_get_path_check_convert(VALUE obj, VALUE tmp, int level)
Definition: file.c:198
features_index_add
static void features_index_add(VALUE feature, VALUE offset)
Definition: load.c:226
ST_DELETE
Definition: st.h:100
rb_get_path
VALUE rb_get_path(VALUE obj)
Definition: file.c:225
rb_vm_struct::expanded_load_path
VALUE expanded_load_path
Definition: vm_core.h:375
get_loaded_features
static VALUE get_loaded_features(void)
Definition: load.c:161
rb_ary_entry
VALUE rb_ary_entry(VALUE ary, long offset)
Definition: array.c:1171
RARRAY_LEN
#define RARRAY_LEN(a)
Definition: ruby.h:878
FALSE
#define FALSE
Definition: nkf.h:174
rb_str_equal
VALUE rb_str_equal(VALUE str1, VALUE str2)
Definition: string.c:2543
rb_load_protect
void rb_load_protect(VALUE fname, int wrap, int *state)
Definition: load.c:656
strlen
size_t strlen(const char *)
dln.h
T_FIXNUM
#define T_FIXNUM
Definition: ruby.h:489
st_table
Definition: st.h:69
RUBY_DTRACE_REQUIRE_ENTRY_ENABLED
#define RUBY_DTRACE_REQUIRE_ENTRY_ENABLED()
Definition: probes.h:18
ST_STOP
Definition: st.h:100
register_init_ext
static int register_init_ext(st_data_t *key, st_data_t *value, st_data_t init, int existing)
Definition: load.c:1042
rb_define_virtual_variable
void rb_define_virtual_variable(const char *, VALUE(*)(ANYARGS), void(*)(ANYARGS))
Definition: variable.c:616
rb_is_absolute_path
int rb_is_absolute_path(const char *path)
Definition: file.c:5281
NORETURN
NORETURN(static void load_failed(VALUE))
node.h
RUBY_DTRACE_FIND_REQUIRE_ENTRY
#define RUBY_DTRACE_FIND_REQUIRE_ENTRY(arg0, arg1, arg2)
Definition: probes.h:25
ruby.h
FilePathValue
#define FilePathValue(v)
Definition: ruby.h:560
rb_usascii_str_new2
#define rb_usascii_str_new2
Definition: intern.h:846
rb_load_internal
static void rb_load_internal(VALUE fname, int wrap)
Definition: load.c:642
Qtrue
#define Qtrue
Definition: ruby.h:426
st_insert
int st_insert(st_table *, st_data_t, st_data_t)
rb_current_realfilepath
VALUE rb_current_realfilepath(void)
Definition: vm_eval.c:1957
RUBY_DTRACE_LOAD_RETURN_ENABLED
#define RUBY_DTRACE_LOAD_RETURN_ENABLED()
Definition: probes.h:33
rb_vm_struct::loaded_features_index
struct st_table * loaded_features_index
Definition: vm_core.h:378
rb_provide_feature
static void rb_provide_feature(VALUE feature)
Definition: load.c:555
loaded_feature_searching::type
int type
Definition: load.c:360
RUBY_DTRACE_FIND_REQUIRE_RETURN_ENABLED
#define RUBY_DTRACE_FIND_REQUIRE_RETURN_ENABLED()
Definition: probes.h:27
rb_provided
int rb_provided(const char *feature)
Definition: load.c:523
SCOPE_SET
#define SCOPE_SET(f)
Definition: eval_intern.h:211
probes.h
ST_CONTINUE
Definition: st.h:100
RUBY_DTRACE_FIND_REQUIRE_ENTRY_ENABLED
#define RUBY_DTRACE_FIND_REQUIRE_ENTRY_ENABLED()
Definition: probes.h:24
eval_intern.h
rb_get_path_check_to_string
VALUE rb_get_path_check_to_string(VALUE obj, int level)
Definition: file.c:176
rb_eTypeError
VALUE rb_eTypeError
Definition: error.c:548
loaded_feature_searching::result
const char * result
Definition: load.c:362
rb_autoload
void rb_autoload(VALUE, ID, const char *)
Definition: variable.c:1607
load_ext
static VALUE load_ext(VALUE path)
Definition: load.c:936
rb_ary_push
VALUE rb_ary_push(VALUE ary, VALUE item)
Definition: array.c:896
rb_ary_tmp_new
VALUE rb_ary_tmp_new(long capa)
Definition: array.c:534
rb_ary_shared_with_p
VALUE rb_ary_shared_with_p(VALUE ary1, VALUE ary2)
Definition: array.c:425
st_get_key
int st_get_key(st_table *, st_data_t, st_data_t *)
Check_Type
#define Check_Type(v, t)
Definition: ruby.h:532
rb_raise
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:1857
RB_GC_GUARD
#define RB_GC_GUARD(v)
Definition: ruby.h:523
rb_f_require_relative
VALUE rb_f_require_relative(VALUE obj, VALUE fname)
Definition: load.c:829
st_init_strtable
st_table * st_init_strtable(void)
Definition: st.c:284
ruby_init_ext
RUBY_FUNC_EXPORTED void ruby_init_ext(const char *name, void(*init)(void))
Definition: load.c:1057
rb_get_load_path
VALUE rb_get_load_path(void)
Definition: load.c:32
T_ARRAY
#define T_ARRAY
Definition: ruby.h:484
PUSH_TAG
#define PUSH_TAG()
Definition: eval_intern.h:141
st_update
int st_update(st_table *table, st_data_t key, st_update_callback_func *func, st_data_t arg)
Definition: st.c:867
rb_define_global_function
void rb_define_global_function(const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a global function.
Definition: class.c:1684
IS_DLEXT
#define IS_DLEXT(e)
Definition: load.c:20
rb_check_id
ID rb_check_id(volatile VALUE *namep)
Returns ID for the given name if it is interned already, or 0.
Definition: ripper.c:17324
FIXNUM_P
#define FIXNUM_P(f)
Definition: ruby.h:347
rb_thread_struct
Definition: vm_core.h:524
rb_load_fail
void rb_load_fail(VALUE path, const char *err)
Definition: error.c:2068
nd_type
#define nd_type(n)
Definition: node.h:282
rb_str_tmp_new
VALUE rb_str_tmp_new(long)
Definition: string.c:919
rb_loaderror
void rb_loaderror(const char *fmt,...)
Definition: error.c:1879
loaded_features_index_clear_i
static int loaded_features_index_clear_i(st_data_t key, st_data_t val, st_data_t arg)
Definition: load.c:265
RUBY_DTRACE_REQUIRE_ENTRY
#define RUBY_DTRACE_REQUIRE_ENTRY(arg0, arg1, arg2)
Definition: probes.h:19
reset_loaded_features_snapshot
static void reset_loaded_features_snapshot(void)
Definition: load.c:167
rb_feature_p
static int rb_feature_p(const char *feature, const char *ext, int rb, int expanded, const char **fn)
Definition: load.c:378
RUBY_DTRACE_LOAD_ENTRY_ENABLED
#define RUBY_DTRACE_LOAD_ENTRY_ENABLED()
Definition: probes.h:30
NODE_MEMO
Definition: node.h:223
RUBY_DTRACE_LOAD_ENTRY
#define RUBY_DTRACE_LOAD_ENTRY(arg0, arg1, arg2)
Definition: probes.h:31
sym
#define sym(x)
Definition: date_core.c:3695
rb_f_require
VALUE rb_f_require(VALUE obj, VALUE fname)
Definition: load.c:815
loadable_ext
static const char *const loadable_ext[]
Definition: load.c:23
st_data_t
RUBY_SYMBOL_EXPORT_BEGIN typedef unsigned long st_data_t
Definition: st.h:20
load_lock
static char * load_lock(const char *ftptr)
Definition: load.c:714
RNode
Definition: node.h:239
rb_exc_raise
void rb_exc_raise(VALUE mesg)
Definition: eval.c:567
EXPAND_HOME
Definition: load.c:41
get_loaded_features_index_raw
static struct st_table * get_loaded_features_index_raw(void)
Definition: load.c:174
rb_load_file_str
void * rb_load_file_str(VALUE)
Definition: ruby.c:1776
DLEXT_MAXLEN
#define DLEXT_MAXLEN
Definition: defines.h:295
RB_TYPE_P
#define RB_TYPE_P(obj, type)
Definition: ruby.h:1664
EXPAND_RELATIVE
Definition: load.c:40
st_lookup
int st_lookup(st_table *, st_data_t, st_data_t *)
IS_SOEXT
#define IS_SOEXT(e)
Definition: load.c:16
rb_ary_free
void rb_ary_free(VALUE ary)
Definition: array.c:540
rb_find_file
VALUE rb_find_file(VALUE path)
Definition: file.c:5499
rb_iseq_new_top
VALUE rb_iseq_new_top(NODE *node, VALUE name, VALUE path, VALUE absolute_path, VALUE parent)
Definition: iseq.c:421
RUBY_DTRACE_REQUIRE_RETURN_ENABLED
#define RUBY_DTRACE_REQUIRE_RETURN_ENABLED()
Definition: probes.h:21
EXEC_TAG
#define EXEC_TAG()
Definition: eval_intern.h:168
rb_str_encode_ospath
VALUE rb_str_encode_ospath(VALUE path)
Definition: file.c:231
rb_ary_cat
VALUE rb_ary_cat(VALUE ary, const VALUE *ptr, long len)
Definition: array.c:907
level
#define level
rb_eRuntimeError
VALUE rb_eRuntimeError
Definition: error.c:547
RUBY_DTRACE_LOAD_RETURN
#define RUBY_DTRACE_LOAD_RETURN(arg0, arg1, arg2)
Definition: probes.h:34
ruby_strdup
char * ruby_strdup(const char *)
Definition: util.c:457
rb_require
VALUE rb_require(const char *fname)
Definition: load.c:1034
rb_class_real
VALUE rb_class_real(VALUE)
Definition: object.c:204
rb_ary_replace
VALUE rb_ary_replace(VALUE copy, VALUE orig)
Definition: array.c:3331
rb_str_cat2
VALUE rb_str_cat2(VALUE, const char *)
Definition: string.c:2159
load_path_getter
static VALUE load_path_getter(ID id, rb_vm_t *vm)
Definition: load.c:155
rb_thread_shield_release
VALUE rb_thread_shield_release(VALUE self)
Definition: thread.c:4734
rb_ary_new
VALUE rb_ary_new(void)
Definition: array.c:495
loaded_feature_path
static VALUE loaded_feature_path(const char *name, long vlen, const char *feature, long len, int type, VALUE load_path)
Definition: load.c:314
rb_vm_struct::load_path_check_cache
VALUE load_path_check_cache
Definition: vm_core.h:374
RArray
Definition: ruby.h:860
JUMP_TAG
#define JUMP_TAG(st)
Definition: eval_intern.h:173
NIL_P
#define NIL_P(v)
Definition: ruby.h:438
release_thread_shield
static int release_thread_shield(st_data_t *key, st_data_t *value, st_data_t done, int existing)
Definition: load.c:754
rb_ary_store
void rb_ary_store(VALUE ary, long idx, VALUE val)
Definition: array.c:790
OBJ_FROZEN
#define OBJ_FROZEN(x)
Definition: ruby.h:1185
EXPAND_NON_CACHE
Definition: load.c:42
rb_thread_struct::top_self
VALUE top_self
Definition: vm_core.h:551
argc
int argc
Definition: ruby.c:131
Qfalse
#define Qfalse
Definition: ruby.h:425
rb_sourcefile
#define rb_sourcefile()
Definition: tcltklib.c:98
rb_intern
#define rb_intern(str)
rb_f_autoload
static VALUE rb_f_autoload(VALUE obj, VALUE sym, VALUE file)
Definition: load.c:1126
rb_cModule
RUBY_EXTERN VALUE rb_cModule
Definition: ruby.h:1572
rb_gc_register_mark_object
void rb_gc_register_mark_object(VALUE obj)
Definition: gc.c:4920
RUBY_FUNC_EXPORTED
#define RUBY_FUNC_EXPORTED
Definition: defines.h:246
MEMCPY
#define MEMCPY(p1, p2, type, n)
Definition: ruby.h:1352
T_NODE
#define T_NODE
Definition: ruby.h:498
rb_provide
void rb_provide(const char *feature)
Definition: load.c:572
rb_str_new2
#define rb_str_new2
Definition: intern.h:840
RNODE
#define RNODE(obj)
Definition: node.h:266
OBJ_FREEZE
#define OBJ_FREEZE(x)
Definition: ruby.h:1186
rb_find_file_safe
VALUE rb_find_file_safe(VALUE path, int safe_level)
Definition: file.c:5505
POP_TAG
#define POP_TAG()
Definition: eval_intern.h:142
rb_vm_top_self
VALUE rb_vm_top_self()
Definition: vm.c:2826
get_loading_table
static st_table * get_loading_table(void)
Definition: load.c:180
numberof
#define numberof(array)
Definition: etc.c:595
rb_file_absolute_path
VALUE rb_file_absolute_path(VALUE fname, VALUE dname)
Definition: file.c:3475
rb_str_resize
VALUE rb_str_resize(VALUE, long)
Definition: string.c:2025
rb_vm_call_cfunc
VALUE rb_vm_call_cfunc(VALUE recv, VALUE(*func)(VALUE), VALUE arg, const rb_block_t *blockptr, VALUE filename)
Definition: vm.c:1732
rb_str_subseq
VALUE rb_str_subseq(VALUE, long, long)
Definition: string.c:1839
rb_alias_variable
void rb_alias_variable(ID, ID)
Definition: variable.c:869
RSTRING_LEN
#define RSTRING_LEN(str)
Definition: ruby.h:841
load_path_getcwd
static VALUE load_path_getcwd(void)
Definition: load.c:100
util.h
TRUE
#define TRUE
Definition: nkf.h:175
rb_vm_cbase
VALUE rb_vm_cbase(void)
Definition: vm.c:1048
rb_vm_struct::loaded_features
VALUE loaded_features
Definition: vm_core.h:376
rb_file_dirname
VALUE rb_file_dirname(VALUE fname)
Definition: file.c:3910
loaded_feature_searching
Definition: load.c:357
rb_load_internal0
static void rb_load_internal0(rb_thread_t *th, VALUE fname, int wrap)
Definition: load.c:580
rb_scan_args
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
Definition: class.c:1728
rb_thread_shield_destroy
VALUE rb_thread_shield_destroy(VALUE self)
Definition: thread.c:4745
buf
unsigned char buf[MIME_BUF_SIZE]
Definition: nkf.c:4308
internal.h
ID
unsigned long ID
Definition: ruby.h:89
loaded_feature_searching::load_path
VALUE load_path
Definition: load.c:361
rb_load
void rb_load(VALUE fname, int wrap)
Definition: load.c:648
loaded_feature_path_i
static int loaded_feature_path_i(st_data_t v, st_data_t b, st_data_t f)
Definition: load.c:366
Qnil
#define Qnil
Definition: ruby.h:427
type
int type
Definition: tcltklib.c:112
VALUE
unsigned long VALUE
Definition: ruby.h:88
rb_mod_autoload_p
static VALUE rb_mod_autoload_p(VALUE mod, VALUE sym)
Definition: load.c:1105
rb_iseq_eval
VALUE rb_iseq_eval(VALUE iseqval)
Definition: vm.c:1642
result
static VALUE result
Definition: nkf.c:40
RBASIC
#define RBASIC(obj)
Definition: ruby.h:1116
strchr
char * strchr(char *, char)
rb_extend_object
void rb_extend_object(VALUE obj, VALUE module)
Definition: eval.c:1305
rb_f_load
static VALUE rb_f_load(int argc, VALUE *argv)
Definition: load.c:684
get_loaded_features_index
static st_table * get_loaded_features_index(void)
Definition: load.c:277
strlcpy
RUBY_EXTERN size_t strlcpy(char *, const char *, size_t)
Definition: strlcpy.c:44
dln_load
void * dln_load(const char *file)
Definition: dln.c:1249
RUBY_DTRACE_FIND_REQUIRE_RETURN
#define RUBY_DTRACE_FIND_REQUIRE_RETURN(arg0, arg1, arg2)
Definition: probes.h:28
rb_define_hooked_variable
void rb_define_hooked_variable(const char *, VALUE *, VALUE(*)(ANYARGS), void(*)(ANYARGS))
Definition: variable.c:585
LONG2NUM
#define LONG2NUM(x)
Definition: ruby.h:1309
my_getcwd
#define my_getcwd()
Definition: util.h:70
rb_str_freeze
VALUE rb_str_freeze(VALUE)
Definition: string.c:1968
StringValueCStr
#define StringValueCStr(v)
Definition: ruby.h:541
rb_set_safe_level_force
void rb_set_safe_level_force(int)
Definition: safe.c:43
features_index_add_single
static void features_index_add_single(VALUE short_feature, VALUE offset)
Definition: load.c:186
expand_type
expand_type
Definition: load.c:38
RSTRING_PTR
#define RSTRING_PTR(str)
Definition: ruby.h:845
NEW_MEMO
#define NEW_MEMO(a, b, c)
Definition: node.h:466
rb_stderr
RUBY_EXTERN VALUE rb_stderr
Definition: ruby.h:1627
rb_thread_shield_new
VALUE rb_thread_shield_new(void)
Definition: thread.c:4698
f
#define f
INT2FIX
#define INT2FIX(i)
Definition: ruby.h:231
rb_thread_struct::top_wrapper
VALUE top_wrapper
Definition: vm_core.h:552
rb_mod_autoload
static VALUE rb_mod_autoload(VALUE mod, VALUE sym, VALUE file)
Definition: load.c:1082
rb_sourceline
int rb_sourceline(void)
Definition: vm.c:1001
rb_module_new
VALUE rb_module_new(void)
Definition: class.c:727
RARRAY_AREF
#define RARRAY_AREF(a, i)
Definition: ruby.h:901
rb_thread_struct::mild_compile_error
int mild_compile_error
Thread-local state of compiling context.
Definition: vm_core.h:608
key
uint8_t key[16]
Definition: random.c:1250
rb_gvar_readonly_setter
void rb_gvar_readonly_setter(VALUE val, ID id, void *data, struct rb_global_variable *gvar)
EXPAND_ALL
Definition: load.c:39
RTEST
#define RTEST(v)
Definition: ruby.h:437
T_STRING
#define T_STRING
Definition: ruby.h:482
rb_construct_expanded_load_path
static void rb_construct_expanded_load_path(int type, int *has_relative, int *has_non_cache)
Definition: load.c:51
rb_vm_struct::load_path_snapshot
VALUE load_path_snapshot
Definition: vm_core.h:373
rb_vm_struct::loaded_features_snapshot
VALUE loaded_features_snapshot
Definition: vm_core.h:377
rb_filesystem_str_new_cstr
VALUE rb_filesystem_str_new_cstr(const char *)
Definition: string.c:737
rb_safe_level
#define rb_safe_level()
Definition: tcltklib.c:95
rb_thread_shield_wait
VALUE rb_thread_shield_wait(VALUE self)
Definition: thread.c:4714
rb_realpath_internal
VALUE rb_realpath_internal(VALUE basedir, VALUE path, int strict)
Definition: file.c:3620
loaded_feature_searching::name
const char * name
Definition: load.c:358
RUBY_DTRACE_REQUIRE_RETURN
#define RUBY_DTRACE_REQUIRE_RETURN(arg0, arg1, arg2)
Definition: probes.h:22
rb_feature_provided
int rb_feature_provided(const char *feature, const char **loading)
Definition: load.c:529
name
const char * name
Definition: nkf.c:208
rb_vm_struct
Definition: vm_core.h:348
rb_find_file_ext_safe
int rb_find_file_ext_safe(VALUE *filep, const char *const *ext, int safe_level)
Definition: file.c:5434
rb_file_load_ok
int rb_file_load_ok(const char *path)
Definition: file.c:5391
StringValuePtr
#define StringValuePtr(v)
Definition: ruby.h:540
search_required
static int search_required(VALUE fname, volatile VALUE *path, int safe_level)
Definition: load.c:840
rb_get_expanded_load_path
VALUE rb_get_expanded_load_path(void)
Definition: load.c:109
load_failed
static void load_failed(VALUE fname)
Definition: load.c:930
rb_warning
void rb_warning(const char *fmt,...)
Definition: error.c:236
rb_f_autoload_p
static VALUE rb_f_autoload_p(VALUE obj, VALUE sym)
Definition: load.c:1147
rb_obj_freeze
VALUE rb_obj_freeze(VALUE)
Definition: object.c:1076
NOEX_PUBLIC
Definition: method.h:25
SPECIAL_CONST_P
#define SPECIAL_CONST_P(x)
Definition: ruby.h:1165
xfree
void void xfree(void *)
rb_vm_struct::load_path
VALUE load_path
Definition: vm_core.h:372
IS_RBEXT
#define IS_RBEXT(e)
Definition: load.c:15
mod
#define mod(x, y)
Definition: date_strftime.c:28
rb_intern2
ID rb_intern2(const char *name, long len)
Definition: ripper.c:17137
load_unlock
static void load_unlock(const char *ftptr, int done)
Definition: load.c:767
Init_load
void Init_load()
Definition: load.c:1158
NULL
#define NULL
Definition: _sdbm.c:103
FIX2LONG
#define FIX2LONG(x)
Definition: ruby.h:345
rb_thread_struct::errinfo
VALUE errinfo
Definition: vm_core.h:573
rb_vm_jump_tag_but_local_jump
void rb_vm_jump_tag_but_local_jump(int state)
Definition: vm.c:1133
GET_THREAD
static rb_thread_t * GET_THREAD(void)
Definition: vm_core.h:927
rb_define_method
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1488
ruby_verbose
#define ruby_verbose
Definition: ruby.h:1475
st_foreach
int st_foreach(st_table *, int(*)(ANYARGS), st_data_t)
Definition: st.c:1034
rb_warn
void rb_warn(const char *fmt,...)
Definition: error.c:223
rb_to_id
ID rb_to_id(VALUE)
Definition: string.c:8730
rb_obj_clone
VALUE rb_obj_clone(VALUE)
Definition: object.c:337
rb_require_safe
VALUE rb_require_safe(VALUE fname, int safe)
Definition: load.c:943
strrchr
char * strrchr(const char *, const char)
loaded_feature_searching::len
long len
Definition: load.c:359
argv
char ** argv
Definition: ruby.c:132
StringValue
#define StringValue(v)
Definition: ruby.h:539
rb_file_expand_path_fast
VALUE rb_file_expand_path_fast(VALUE fname, VALUE dname)
Definition: file.c:3428
rb_autoload_p
VALUE rb_autoload_p(VALUE, ID)
Definition: variable.c:1814
xcalloc
#define xcalloc
Definition: defines.h:110
GET_VM
#define GET_VM()
Definition: vm_core.h:920