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