Ruby 2.0.0p353(2013-11-22revision43784)

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