Ruby  2.1.10p492(2016-04-01revision54464)
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 
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
33 {
34  VALUE load_path = GET_VM()->load_path;
35  return load_path;
36 }
37 
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;
97 }
98 
99 static VALUE
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
110 {
111  rb_vm_t *vm = GET_VM();
112  const VALUE non_cache = Qtrue;
113 
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) {
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. */
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;
143  &has_relative, &has_non_cache);
144  }
145  else {
146  /* Expand only tilde (User HOME) and non-cacheable objects. */
148  &has_relative, &has_non_cache);
149  }
150  }
151  return vm->expanded_load_path;
152 }
153 
154 static VALUE
156 {
157  return vm->load_path;
158 }
159 
160 static VALUE
162 {
163  return GET_VM()->loaded_features;
164 }
165 
166 static void
168 {
169  rb_vm_t *vm = GET_VM();
171 }
172 
173 static struct st_table *
175 {
176  return GET_VM()->loaded_features_index;
177 }
178 
179 static st_table *
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
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
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 *
278 {
279  VALUE features;
280  int i;
281  rb_vm_t *vm = GET_VM();
282 
284  /* The sharing was broken; something (other than us in rb_provide_feature())
285  modified loaded_features. Rebuild the index. */
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  }
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 (strchr(feature, '.') && !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 
358  const char *name;
359  long len;
360  int type;
362  const char *result;
363 };
364 
365 static int
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;
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;
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
556 {
557  VALUE features;
558 
559  features = get_loaded_features();
560  if (OBJ_FROZEN(features)) {
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));
569 }
570 
571 void
572 rb_provide(const char *feature)
573 {
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 */
599  th->top_wrapper = rb_module_new();
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) {
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
685 {
686  VALUE fname, wrap, path, orig_fname;
687 
688  rb_scan_args(argc, argv, "11", &fname, &wrap);
689 
692  rb_sourcefile(),
693  rb_sourceline());
694  }
695 
696  orig_fname = FilePathValue(fname);
697  fname = rb_str_encode_ospath(orig_fname);
698  path = rb_find_file(fname);
699  if (!path) {
700  if (!rb_file_load_ok(RSTRING_PTR(fname)))
701  load_failed(orig_fname);
702  path = fname;
703  }
704  rb_load_internal(path, RTEST(wrap));
705 
708  rb_sourcefile(),
709  rb_sourceline());
710  }
711 
712  return Qtrue;
713 }
714 
715 static char *
716 load_lock(const char *ftptr)
717 {
718  st_data_t data;
719  st_table *loading_tbl = get_loading_table();
720 
721  if (!loading_tbl || !st_lookup(loading_tbl, (st_data_t)ftptr, &data)) {
722  /* loading ruby library should be serialized. */
723  if (!loading_tbl) {
724  GET_VM()->loading_table = loading_tbl = st_init_strtable();
725  }
726  /* partial state */
727  ftptr = ruby_strdup(ftptr);
729  st_insert(loading_tbl, (st_data_t)ftptr, data);
730  return (char *)ftptr;
731  }
732  else if (RB_TYPE_P((VALUE)data, T_NODE) && nd_type((VALUE)data) == NODE_MEMO) {
733  NODE *memo = RNODE(data);
734  void (*init)(void) = (void (*)(void))memo->nd_cfnc;
736  st_insert(loading_tbl, (st_data_t)ftptr, data);
737  (*init)();
738  return (char *)"";
739  }
740  if (RTEST(ruby_verbose)) {
741  rb_warning("loading in progress, circular require considered harmful - %s", ftptr);
743  }
744  switch (rb_thread_shield_wait((VALUE)data)) {
745  case Qfalse:
746  data = (st_data_t)ftptr;
747  st_insert(loading_tbl, data, (st_data_t)rb_thread_shield_new());
748  return 0;
749  case Qnil:
750  return 0;
751  }
752  return (char *)ftptr;
753 }
754 
755 static int
757 {
758  VALUE thread_shield = (VALUE)*value;
759  if (!existing) return ST_STOP;
760  if (done ? rb_thread_shield_destroy(thread_shield) : rb_thread_shield_release(thread_shield)) {
761  /* still in-use */
762  return ST_CONTINUE;
763  }
764  xfree((char *)*key);
765  return ST_DELETE;
766 }
767 
768 static void
769 load_unlock(const char *ftptr, int done)
770 {
771  if (ftptr) {
772  st_data_t key = (st_data_t)ftptr;
773  st_table *loading_tbl = get_loading_table();
774 
775  st_update(loading_tbl, key, release_thread_shield, done);
776  }
777 }
778 
779 
780 /*
781  * call-seq:
782  * require(name) -> true or false
783  *
784  * Loads the given +name+, returning +true+ if successful and +false+ if the
785  * feature is already loaded.
786  *
787  * If the filename does not resolve to an absolute path, it will be searched
788  * for in the directories listed in <code>$LOAD_PATH</code> (<code>$:</code>).
789  *
790  * If the filename has the extension ".rb", it is loaded as a source file; if
791  * the extension is ".so", ".o", or ".dll", or the default shared library
792  * extension on the current platform, Ruby loads the shared library as a
793  * Ruby extension. Otherwise, Ruby tries adding ".rb", ".so", and so on
794  * to the name until found. If the file named cannot be found, a LoadError
795  * will be raised.
796  *
797  * For Ruby extensions the filename given may use any shared library
798  * extension. For example, on Linux the socket extension is "socket.so" and
799  * <code>require 'socket.dll'</code> will load the socket extension.
800  *
801  * The absolute path of the loaded file is added to
802  * <code>$LOADED_FEATURES</code> (<code>$"</code>). A file will not be
803  * loaded again if its path already appears in <code>$"</code>. For example,
804  * <code>require 'a'; require './a'</code> will not load <code>a.rb</code>
805  * again.
806  *
807  * require "my-library.rb"
808  * require "db-driver"
809  *
810  * Any constants or globals within the loaded source file will be available
811  * in the calling program's global namespace. However, local variables will
812  * not be propagated to the loading environment.
813  *
814  */
815 
816 VALUE
818 {
819  return rb_require_safe(fname, rb_safe_level());
820 }
821 
822 /*
823  * call-seq:
824  * require_relative(string) -> true or false
825  *
826  * Ruby tries to load the library named _string_ relative to the requiring
827  * file's path. If the file's path cannot be determined a LoadError is raised.
828  * If a file is loaded +true+ is returned and false otherwise.
829  */
830 VALUE
832 {
834  if (NIL_P(base)) {
835  rb_loaderror("cannot infer basepath");
836  }
837  base = rb_file_dirname(base);
838  return rb_require_safe(rb_file_absolute_path(fname, base), rb_safe_level());
839 }
840 
841 static int
842 search_required(VALUE fname, volatile VALUE *path, int safe_level)
843 {
844  VALUE tmp;
845  char *ext, *ftptr;
846  int type, ft = 0;
847  const char *loading;
848 
849  *path = 0;
850  ext = strrchr(ftptr = RSTRING_PTR(fname), '.');
851  if (ext && !strchr(ext, '/')) {
852  if (IS_RBEXT(ext)) {
853  if (rb_feature_p(ftptr, ext, TRUE, FALSE, &loading)) {
854  if (loading) *path = rb_filesystem_str_new_cstr(loading);
855  return 'r';
856  }
857  if ((tmp = rb_find_file_safe(fname, safe_level)) != 0) {
858  ext = strrchr(ftptr = RSTRING_PTR(tmp), '.');
859  if (!rb_feature_p(ftptr, ext, TRUE, TRUE, &loading) || loading)
860  *path = tmp;
861  return 'r';
862  }
863  return 0;
864  }
865  else if (IS_SOEXT(ext)) {
866  if (rb_feature_p(ftptr, ext, FALSE, FALSE, &loading)) {
867  if (loading) *path = rb_filesystem_str_new_cstr(loading);
868  return 's';
869  }
870  tmp = rb_str_subseq(fname, 0, ext - RSTRING_PTR(fname));
871 #ifdef DLEXT2
872  OBJ_FREEZE(tmp);
873  if (rb_find_file_ext_safe(&tmp, loadable_ext + 1, safe_level)) {
874  ext = strrchr(ftptr = RSTRING_PTR(tmp), '.');
875  if (!rb_feature_p(ftptr, ext, FALSE, TRUE, &loading) || loading)
876  *path = tmp;
877  return 's';
878  }
879 #else
880  rb_str_cat2(tmp, DLEXT);
881  OBJ_FREEZE(tmp);
882  if ((tmp = rb_find_file_safe(tmp, safe_level)) != 0) {
883  ext = strrchr(ftptr = RSTRING_PTR(tmp), '.');
884  if (!rb_feature_p(ftptr, ext, FALSE, TRUE, &loading) || loading)
885  *path = tmp;
886  return 's';
887  }
888 #endif
889  }
890  else if (IS_DLEXT(ext)) {
891  if (rb_feature_p(ftptr, ext, FALSE, FALSE, &loading)) {
892  if (loading) *path = rb_filesystem_str_new_cstr(loading);
893  return 's';
894  }
895  if ((tmp = rb_find_file_safe(fname, safe_level)) != 0) {
896  ext = strrchr(ftptr = RSTRING_PTR(tmp), '.');
897  if (!rb_feature_p(ftptr, ext, FALSE, TRUE, &loading) || loading)
898  *path = tmp;
899  return 's';
900  }
901  }
902  }
903  else if ((ft = rb_feature_p(ftptr, 0, FALSE, FALSE, &loading)) == 'r') {
904  if (loading) *path = rb_filesystem_str_new_cstr(loading);
905  return 'r';
906  }
907  tmp = fname;
908  type = rb_find_file_ext_safe(&tmp, loadable_ext, safe_level);
909  switch (type) {
910  case 0:
911  if (ft)
912  goto statically_linked;
913  ftptr = RSTRING_PTR(tmp);
914  return rb_feature_p(ftptr, 0, FALSE, TRUE, 0);
915 
916  default:
917  if (ft) {
918  statically_linked:
919  if (loading) *path = rb_filesystem_str_new_cstr(loading);
920  return ft;
921  }
922  case 1:
923  ext = strrchr(ftptr = RSTRING_PTR(tmp), '.');
924  if (rb_feature_p(ftptr, ext, !--type, TRUE, &loading) && !loading)
925  break;
926  *path = tmp;
927  }
928  return type ? 's' : 'r';
929 }
930 
931 static void
933 {
934  rb_load_fail(fname, "cannot load such file");
935 }
936 
937 static VALUE
939 {
941  return (VALUE)dln_load(RSTRING_PTR(path));
942 }
943 
944 VALUE
945 rb_require_safe(VALUE fname, int safe)
946 {
947  volatile VALUE result = Qnil;
948  rb_thread_t *th = GET_THREAD();
949  volatile VALUE errinfo = th->errinfo;
950  int state;
951  struct {
952  int safe;
953  } volatile saved;
954  char *volatile ftptr = 0;
955 
958  rb_sourcefile(),
959  rb_sourceline());
960  }
961 
962  PUSH_TAG();
963  saved.safe = rb_safe_level();
964  if ((state = EXEC_TAG()) == 0) {
965  VALUE path;
966  long handle;
967  int found;
968 
970  FilePathValue(fname);
972 
975  rb_sourcefile(),
976  rb_sourceline());
977  }
978 
979  path = rb_str_encode_ospath(fname);
980  found = search_required(path, &path, safe);
981 
984  rb_sourcefile(),
985  rb_sourceline());
986  }
987  if (found) {
988  if (!path || !(ftptr = load_lock(RSTRING_PTR(path)))) {
989  result = Qfalse;
990  }
991  else if (!*ftptr) {
992  rb_provide_feature(path);
993  result = Qtrue;
994  }
995  else {
996  switch (found) {
997  case 'r':
998  rb_load_internal(path, 0);
999  break;
1000 
1001  case 's':
1002  handle = (long)rb_vm_call_cfunc(rb_vm_top_self(), load_ext,
1003  path, 0, path);
1005  break;
1006  }
1007  rb_provide_feature(path);
1008  result = Qtrue;
1009  }
1010  }
1011  }
1012  POP_TAG();
1013  load_unlock(ftptr, !state);
1014 
1015  rb_set_safe_level_force(saved.safe);
1016  if (state) {
1017  JUMP_TAG(state);
1018  }
1019 
1020  if (NIL_P(result)) {
1021  load_failed(fname);
1022  }
1023 
1024  th->errinfo = errinfo;
1025 
1028  rb_sourcefile(),
1029  rb_sourceline());
1030  }
1031 
1032  return result;
1033 }
1034 
1035 VALUE
1036 rb_require(const char *fname)
1037 {
1038  VALUE fn = rb_str_new2(fname);
1039  OBJ_FREEZE(fn);
1040  return rb_require_safe(fn, rb_safe_level());
1041 }
1042 
1043 static int
1044 register_init_ext(st_data_t *key, st_data_t *value, st_data_t init, int existing)
1045 {
1046  const char *name = (char *)*key;
1047  if (existing) {
1048  /* already registered */
1049  rb_warn("%s is already registered", name);
1050  }
1051  else {
1052  *value = (st_data_t)NEW_MEMO(init, 0, 0);
1054  }
1055  return ST_CONTINUE;
1056 }
1057 
1058 RUBY_FUNC_EXPORTED void
1059 ruby_init_ext(const char *name, void (*init)(void))
1060 {
1061  st_table *loading_tbl = get_loading_table();
1062 
1063  if (!loading_tbl) {
1064  GET_VM()->loading_table = loading_tbl = st_init_strtable();
1065  }
1066  st_update(loading_tbl, (st_data_t)name, register_init_ext, (st_data_t)init);
1067 }
1068 
1069 /*
1070  * call-seq:
1071  * mod.autoload(module, filename) -> nil
1072  *
1073  * Registers _filename_ to be loaded (using <code>Kernel::require</code>)
1074  * the first time that _module_ (which may be a <code>String</code> or
1075  * a symbol) is accessed in the namespace of _mod_.
1076  *
1077  * module A
1078  * end
1079  * A.autoload(:B, "b")
1080  * A::B.doit # autoloads "b"
1081  */
1082 
1083 static VALUE
1085 {
1086  ID id = rb_to_id(sym);
1087 
1088  FilePathValue(file);
1089  rb_autoload(mod, id, RSTRING_PTR(file));
1090  return Qnil;
1091 }
1092 
1093 /*
1094  * call-seq:
1095  * mod.autoload?(name) -> String or nil
1096  *
1097  * Returns _filename_ to be loaded if _name_ is registered as
1098  * +autoload+ in the namespace of _mod_.
1099  *
1100  * module A
1101  * end
1102  * A.autoload(:B, "b")
1103  * A.autoload?(:B) #=> "b"
1104  */
1105 
1106 static VALUE
1108 {
1109  ID id = rb_check_id(&sym);
1110  if (!id) {
1111  return Qnil;
1112  }
1113  return rb_autoload_p(mod, id);
1114 }
1115 
1116 /*
1117  * call-seq:
1118  * autoload(module, filename) -> nil
1119  *
1120  * Registers _filename_ to be loaded (using <code>Kernel::require</code>)
1121  * the first time that _module_ (which may be a <code>String</code> or
1122  * a symbol) is accessed.
1123  *
1124  * autoload(:MyModule, "/usr/local/lib/modules/my_module.rb")
1125  */
1126 
1127 static VALUE
1129 {
1130  VALUE klass = rb_class_real(rb_vm_cbase());
1131  if (NIL_P(klass)) {
1132  rb_raise(rb_eTypeError, "Can not set autoload on singleton class");
1133  }
1134  return rb_mod_autoload(klass, sym, file);
1135 }
1136 
1137 /*
1138  * call-seq:
1139  * autoload?(name) -> String or nil
1140  *
1141  * Returns _filename_ to be loaded if _name_ is registered as
1142  * +autoload+.
1143  *
1144  * autoload(:B, "b")
1145  * autoload?(:B) #=> "b"
1146  */
1147 
1148 static VALUE
1150 {
1151  /* use rb_vm_cbase() as same as rb_f_autoload. */
1152  VALUE klass = rb_vm_cbase();
1153  if (NIL_P(klass)) {
1154  return Qnil;
1155  }
1156  return rb_mod_autoload_p(klass, sym);
1157 }
1158 
1159 void
1161 {
1162 #undef rb_intern
1163 #define rb_intern(str) rb_intern2((str), strlen(str))
1164  rb_vm_t *vm = GET_VM();
1165  static const char var_load_path[] = "$:";
1166  ID id_load_path = rb_intern2(var_load_path, sizeof(var_load_path)-1);
1167 
1169  rb_alias_variable(rb_intern("$-I"), id_load_path);
1170  rb_alias_variable(rb_intern("$LOAD_PATH"), id_load_path);
1171  vm->load_path = rb_ary_new();
1172  vm->expanded_load_path = rb_ary_tmp_new(0);
1173  vm->load_path_snapshot = rb_ary_tmp_new(0);
1174  vm->load_path_check_cache = 0;
1175 
1177  rb_define_virtual_variable("$LOADED_FEATURES", get_loaded_features, 0);
1178  vm->loaded_features = rb_ary_new();
1179  vm->loaded_features_snapshot = rb_ary_tmp_new(0);
1180  vm->loaded_features_index = st_init_strtable();
1181 
1182  rb_define_global_function("load", rb_f_load, -1);
1183  rb_define_global_function("require", rb_f_require, 1);
1184  rb_define_global_function("require_relative", rb_f_require_relative, 1);
1185  rb_define_method(rb_cModule, "autoload", rb_mod_autoload, 2);
1186  rb_define_method(rb_cModule, "autoload?", rb_mod_autoload_p, 1);
1187  rb_define_global_function("autoload", rb_f_autoload, 2);
1188  rb_define_global_function("autoload?", rb_f_autoload_p, 1);
1189 
1192 }
VALUE ruby_dln_librefs
Definition: load.c:13
void rb_backtrace_print_to(VALUE output)
Definition: vm_backtrace.c:803
VALUE rb_get_path_check_convert(VALUE obj, VALUE tmp, int level)
Definition: file.c:199
static void features_index_add(VALUE feature, VALUE offset)
Definition: load.c:226
Definition: st.h:100
VALUE rb_get_path(VALUE obj)
Definition: file.c:226
VALUE expanded_load_path
Definition: vm_core.h:375
static VALUE get_loaded_features(void)
Definition: load.c:161
VALUE rb_ary_entry(VALUE ary, long offset)
Definition: array.c:1179
#define RARRAY_LEN(a)
Definition: ruby.h:878
#define FALSE
Definition: nkf.h:174
VALUE rb_str_equal(VALUE str1, VALUE str2)
Definition: string.c:2542
void rb_load_protect(VALUE fname, int wrap, int *state)
Definition: load.c:656
size_t strlen(const char *)
#define T_FIXNUM
Definition: ruby.h:489
Definition: st.h:69
#define RUBY_DTRACE_REQUIRE_ENTRY_ENABLED()
Definition: probes.h:18
Definition: st.h:100
static int register_init_ext(st_data_t *key, st_data_t *value, st_data_t init, int existing)
Definition: load.c:1044
void rb_define_virtual_variable(const char *, VALUE(*)(ANYARGS), void(*)(ANYARGS))
Definition: variable.c:616
int rb_is_absolute_path(const char *path)
Definition: file.c:5282
NORETURN(static void load_failed(VALUE))
#define RUBY_DTRACE_FIND_REQUIRE_ENTRY(arg0, arg1, arg2)
Definition: probes.h:25
#define FilePathValue(v)
Definition: ruby.h:560
#define rb_usascii_str_new2
Definition: intern.h:846
static void rb_load_internal(VALUE fname, int wrap)
Definition: load.c:642
#define Qtrue
Definition: ruby.h:426
int st_insert(st_table *, st_data_t, st_data_t)
VALUE rb_current_realfilepath(void)
Definition: vm_eval.c:1964
#define RUBY_DTRACE_LOAD_RETURN_ENABLED()
Definition: probes.h:33
struct st_table * loaded_features_index
Definition: vm_core.h:378
static void rb_provide_feature(VALUE feature)
Definition: load.c:555
#define RUBY_DTRACE_FIND_REQUIRE_RETURN_ENABLED()
Definition: probes.h:27
int rb_provided(const char *feature)
Definition: load.c:523
#define SCOPE_SET(f)
Definition: eval_intern.h:211
#define RUBY_DTRACE_FIND_REQUIRE_ENTRY_ENABLED()
Definition: probes.h:24
VALUE rb_get_path_check_to_string(VALUE obj, int level)
Definition: file.c:177
VALUE rb_eTypeError
Definition: error.c:548
const char * result
Definition: load.c:362
void rb_autoload(VALUE, ID, const char *)
Definition: variable.c:1607
static VALUE load_ext(VALUE path)
Definition: load.c:938
VALUE rb_ary_push(VALUE ary, VALUE item)
Definition: array.c:900
VALUE rb_ary_tmp_new(long capa)
Definition: array.c:538
VALUE rb_ary_shared_with_p(VALUE ary1, VALUE ary2)
Definition: array.c:429
int st_get_key(st_table *, st_data_t, st_data_t *)
#define Check_Type(v, t)
Definition: ruby.h:532
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:1857
#define RB_GC_GUARD(v)
Definition: ruby.h:523
VALUE rb_f_require_relative(VALUE obj, VALUE fname)
Definition: load.c:831
st_table * st_init_strtable(void)
Definition: st.c:284
RUBY_FUNC_EXPORTED void ruby_init_ext(const char *name, void(*init)(void))
Definition: load.c:1059
VALUE rb_get_load_path(void)
Definition: load.c:32
#define T_ARRAY
Definition: ruby.h:484
#define PUSH_TAG()
Definition: eval_intern.h:141
int st_update(st_table *table, st_data_t key, st_update_callback_func *func, st_data_t arg)
Definition: st.c:867
void rb_define_global_function(const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a global function.
Definition: class.c:1675
#define IS_DLEXT(e)
Definition: load.c:20
ID rb_check_id(volatile VALUE *namep)
Returns ID for the given name if it is interned already, or 0.
Definition: ripper.c:17365
#define FIXNUM_P(f)
Definition: ruby.h:347
void rb_load_fail(VALUE path, const char *err)
Definition: error.c:2068
#define nd_type(n)
Definition: node.h:282
VALUE rb_str_tmp_new(long)
Definition: string.c:919
void rb_loaderror(const char *fmt,...)
Definition: error.c:1879
static int loaded_features_index_clear_i(st_data_t key, st_data_t val, st_data_t arg)
Definition: load.c:265
#define RUBY_DTRACE_REQUIRE_ENTRY(arg0, arg1, arg2)
Definition: probes.h:19
static void reset_loaded_features_snapshot(void)
Definition: load.c:167
static int rb_feature_p(const char *feature, const char *ext, int rb, int expanded, const char **fn)
Definition: load.c:378
#define RUBY_DTRACE_LOAD_ENTRY_ENABLED()
Definition: probes.h:30
#define RUBY_DTRACE_LOAD_ENTRY(arg0, arg1, arg2)
Definition: probes.h:31
#define sym(x)
Definition: date_core.c:3695
VALUE rb_f_require(VALUE obj, VALUE fname)
Definition: load.c:817
static const char *const loadable_ext[]
Definition: load.c:23
RUBY_SYMBOL_EXPORT_BEGIN typedef unsigned long st_data_t
Definition: st.h:20
static char * load_lock(const char *ftptr)
Definition: load.c:716
Definition: node.h:239
void rb_exc_raise(VALUE mesg)
Definition: eval.c:567
static struct st_table * get_loaded_features_index_raw(void)
Definition: load.c:174
void * rb_load_file_str(VALUE)
Definition: ruby.c:1776
#define DLEXT_MAXLEN
Definition: defines.h:295
#define RB_TYPE_P(obj, type)
Definition: ruby.h:1672
int st_lookup(st_table *, st_data_t, st_data_t *)
#define IS_SOEXT(e)
Definition: load.c:16
void rb_ary_free(VALUE ary)
Definition: array.c:544
VALUE rb_find_file(VALUE path)
Definition: file.c:5508
VALUE rb_iseq_new_top(NODE *node, VALUE name, VALUE path, VALUE absolute_path, VALUE parent)
Definition: iseq.c:421
#define RUBY_DTRACE_REQUIRE_RETURN_ENABLED()
Definition: probes.h:21
#define EXEC_TAG()
Definition: eval_intern.h:168
VALUE rb_str_encode_ospath(VALUE path)
Definition: file.c:232
VALUE rb_ary_cat(VALUE ary, const VALUE *ptr, long len)
Definition: array.c:911
#define level
VALUE rb_eRuntimeError
Definition: error.c:547
#define RUBY_DTRACE_LOAD_RETURN(arg0, arg1, arg2)
Definition: probes.h:34
char * ruby_strdup(const char *)
Definition: util.c:461
VALUE rb_require(const char *fname)
Definition: load.c:1036
VALUE rb_class_real(VALUE)
Definition: object.c:204
VALUE rb_ary_replace(VALUE copy, VALUE orig)
Definition: array.c:3342
VALUE rb_str_cat2(VALUE, const char *)
Definition: string.c:2158
static VALUE load_path_getter(ID id, rb_vm_t *vm)
Definition: load.c:155
VALUE rb_thread_shield_release(VALUE self)
Definition: thread.c:4738
VALUE rb_ary_new(void)
Definition: array.c:499
static VALUE loaded_feature_path(const char *name, long vlen, const char *feature, long len, int type, VALUE load_path)
Definition: load.c:314
VALUE load_path_check_cache
Definition: vm_core.h:374
Definition: ruby.h:860
#define JUMP_TAG(st)
Definition: eval_intern.h:173
#define NIL_P(v)
Definition: ruby.h:438
static int release_thread_shield(st_data_t *key, st_data_t *value, st_data_t done, int existing)
Definition: load.c:756
void rb_ary_store(VALUE ary, long idx, VALUE val)
Definition: array.c:794
#define OBJ_FROZEN(x)
Definition: ruby.h:1193
VALUE top_self
Definition: vm_core.h:551
int argc
Definition: ruby.c:131
#define Qfalse
Definition: ruby.h:425
#define rb_sourcefile()
Definition: tcltklib.c:98
#define rb_intern(str)
static VALUE rb_f_autoload(VALUE obj, VALUE sym, VALUE file)
Definition: load.c:1128
RUBY_EXTERN VALUE rb_cModule
Definition: ruby.h:1580
void rb_gc_register_mark_object(VALUE obj)
Definition: gc.c:4923
#define RUBY_FUNC_EXPORTED
Definition: defines.h:246
#define MEMCPY(p1, p2, type, n)
Definition: ruby.h:1360
#define T_NODE
Definition: ruby.h:498
void rb_provide(const char *feature)
Definition: load.c:572
#define rb_str_new2
Definition: intern.h:840
#define RNODE(obj)
Definition: node.h:266
#define OBJ_FREEZE(x)
Definition: ruby.h:1194
VALUE rb_find_file_safe(VALUE path, int safe_level)
Definition: file.c:5514
#define POP_TAG()
Definition: eval_intern.h:142
VALUE rb_vm_top_self()
Definition: vm.c:2834
static st_table * get_loading_table(void)
Definition: load.c:180
#define numberof(array)
Definition: etc.c:602
VALUE rb_file_absolute_path(VALUE fname, VALUE dname)
Definition: file.c:3476
VALUE rb_str_resize(VALUE, long)
Definition: string.c:2024
VALUE rb_vm_call_cfunc(VALUE recv, VALUE(*func)(VALUE), VALUE arg, const rb_block_t *blockptr, VALUE filename)
Definition: vm.c:1736
VALUE rb_str_subseq(VALUE, long, long)
Definition: string.c:1838
void rb_alias_variable(ID, ID)
Definition: variable.c:869
#define RSTRING_LEN(str)
Definition: ruby.h:841
static VALUE load_path_getcwd(void)
Definition: load.c:100
#define TRUE
Definition: nkf.h:175
VALUE rb_vm_cbase(void)
Definition: vm.c:1048
VALUE loaded_features
Definition: vm_core.h:376
VALUE rb_file_dirname(VALUE fname)
Definition: file.c:3911
static void rb_load_internal0(rb_thread_t *th, VALUE fname, int wrap)
Definition: load.c:580
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
Definition: class.c:1719
VALUE rb_thread_shield_destroy(VALUE self)
Definition: thread.c:4749
unsigned char buf[MIME_BUF_SIZE]
Definition: nkf.c:4308
unsigned long ID
Definition: ruby.h:89
void rb_load(VALUE fname, int wrap)
Definition: load.c:648
static int loaded_feature_path_i(st_data_t v, st_data_t b, st_data_t f)
Definition: load.c:366
#define Qnil
Definition: ruby.h:427
int type
Definition: tcltklib.c:112
unsigned long VALUE
Definition: ruby.h:88
static VALUE rb_mod_autoload_p(VALUE mod, VALUE sym)
Definition: load.c:1107
VALUE rb_iseq_eval(VALUE iseqval)
Definition: vm.c:1646
static VALUE result
Definition: nkf.c:40
#define RBASIC(obj)
Definition: ruby.h:1116
char * strchr(char *, char)
void rb_extend_object(VALUE obj, VALUE module)
Definition: eval.c:1318
static VALUE rb_f_load(int argc, VALUE *argv)
Definition: load.c:684
static st_table * get_loaded_features_index(void)
Definition: load.c:277
RUBY_EXTERN size_t strlcpy(char *, const char *, size_t)
Definition: strlcpy.c:44
void * dln_load(const char *file)
Definition: dln.c:1250
#define RUBY_DTRACE_FIND_REQUIRE_RETURN(arg0, arg1, arg2)
Definition: probes.h:28
void rb_define_hooked_variable(const char *, VALUE *, VALUE(*)(ANYARGS), void(*)(ANYARGS))
Definition: variable.c:585
#define LONG2NUM(x)
Definition: ruby.h:1317
#define my_getcwd()
Definition: util.h:70
VALUE rb_str_freeze(VALUE)
Definition: string.c:1967
#define StringValueCStr(v)
Definition: ruby.h:541
void rb_set_safe_level_force(int)
Definition: safe.c:43
static void features_index_add_single(VALUE short_feature, VALUE offset)
Definition: load.c:186
expand_type
Definition: load.c:38
#define RSTRING_PTR(str)
Definition: ruby.h:845
#define NEW_MEMO(a, b, c)
Definition: node.h:466
RUBY_EXTERN VALUE rb_stderr
Definition: ruby.h:1635
VALUE rb_thread_shield_new(void)
Definition: thread.c:4702
#define f
#define INT2FIX(i)
Definition: ruby.h:231
VALUE top_wrapper
Definition: vm_core.h:552
static VALUE rb_mod_autoload(VALUE mod, VALUE sym, VALUE file)
Definition: load.c:1084
int rb_sourceline(void)
Definition: vm.c:1001
VALUE rb_module_new(void)
Definition: class.c:708
#define RARRAY_AREF(a, i)
Definition: ruby.h:901
int mild_compile_error
Thread-local state of compiling context.
Definition: vm_core.h:608
uint8_t key[16]
Definition: random.c:1250
void rb_gvar_readonly_setter(VALUE val, ID id, void *data, struct rb_global_variable *gvar)
#define RTEST(v)
Definition: ruby.h:437
#define T_STRING
Definition: ruby.h:482
static void rb_construct_expanded_load_path(int type, int *has_relative, int *has_non_cache)
Definition: load.c:51
VALUE load_path_snapshot
Definition: vm_core.h:373
VALUE loaded_features_snapshot
Definition: vm_core.h:377
VALUE rb_filesystem_str_new_cstr(const char *)
Definition: string.c:737
#define rb_safe_level()
Definition: tcltklib.c:95
VALUE rb_thread_shield_wait(VALUE self)
Definition: thread.c:4718
VALUE rb_realpath_internal(VALUE basedir, VALUE path, int strict)
Definition: file.c:3621
const char * name
Definition: load.c:358
#define RUBY_DTRACE_REQUIRE_RETURN(arg0, arg1, arg2)
Definition: probes.h:22
int rb_feature_provided(const char *feature, const char **loading)
Definition: load.c:529
const char * name
Definition: nkf.c:208
int rb_find_file_ext_safe(VALUE *filep, const char *const *ext, int safe_level)
Definition: file.c:5443
int rb_file_load_ok(const char *path)
Definition: file.c:5398
#define StringValuePtr(v)
Definition: ruby.h:540
static int search_required(VALUE fname, volatile VALUE *path, int safe_level)
Definition: load.c:842
VALUE rb_get_expanded_load_path(void)
Definition: load.c:109
static void load_failed(VALUE fname)
Definition: load.c:932
void rb_warning(const char *fmt,...)
Definition: error.c:236
static VALUE rb_f_autoload_p(VALUE obj, VALUE sym)
Definition: load.c:1149
VALUE rb_obj_freeze(VALUE)
Definition: object.c:1070
#define SPECIAL_CONST_P(x)
Definition: ruby.h:1165
void void xfree(void *)
VALUE load_path
Definition: vm_core.h:372
#define IS_RBEXT(e)
Definition: load.c:15
#define mod(x, y)
Definition: date_strftime.c:28
ID rb_intern2(const char *name, long len)
Definition: ripper.c:17178
static void load_unlock(const char *ftptr, int done)
Definition: load.c:769
void Init_load()
Definition: load.c:1160
#define NULL
Definition: _sdbm.c:102
#define FIX2LONG(x)
Definition: ruby.h:345
void rb_vm_jump_tag_but_local_jump(int state)
Definition: vm.c:1133
static rb_thread_t * GET_THREAD(void)
Definition: vm_core.h:929
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1479
#define ruby_verbose
Definition: ruby.h:1483
int st_foreach(st_table *, int(*)(ANYARGS), st_data_t)
Definition: st.c:1034
void rb_warn(const char *fmt,...)
Definition: error.c:223
ID rb_to_id(VALUE)
Definition: string.c:8734
VALUE rb_obj_clone(VALUE)
Definition: object.c:337
VALUE rb_require_safe(VALUE fname, int safe)
Definition: load.c:945
char * strrchr(const char *, const char)
char ** argv
Definition: ruby.c:132
#define StringValue(v)
Definition: ruby.h:539
VALUE rb_file_expand_path_fast(VALUE fname, VALUE dname)
Definition: file.c:3429
VALUE rb_autoload_p(VALUE, ID)
Definition: variable.c:1814
#define xcalloc
Definition: defines.h:110
#define GET_VM()
Definition: vm_core.h:922