Ruby  2.1.3p242(2014-09-19revision47630)
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 (!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;
447  if (!load_path) load_path = rb_get_expanded_load_path();
448  if (!(p = loaded_feature_path(f, n, feature, len, type, load_path)))
449  continue;
450  expanded = 1;
451  f += RSTRING_LEN(p) + 1;
452  }
453  if (!*(e = f + len)) {
454  if (ext) continue;
455  return 'u';
456  }
457  if (*e != '.') continue;
458  if ((!rb || !ext) && (IS_SOEXT(e) || IS_DLEXT(e))) {
459  return 's';
460  }
461  if ((rb || !ext) && (IS_RBEXT(e))) {
462  return 'r';
463  }
464  }
465  }
466 
467  loading_tbl = get_loading_table();
468  if (loading_tbl) {
469  f = 0;
470  if (!expanded) {
471  struct loaded_feature_searching fs;
472  fs.name = feature;
473  fs.len = len;
474  fs.type = type;
475  fs.load_path = load_path ? load_path : rb_get_expanded_load_path();
476  fs.result = 0;
477  st_foreach(loading_tbl, loaded_feature_path_i, (st_data_t)&fs);
478  if ((f = fs.result) != 0) {
479  if (fn) *fn = f;
480  goto loading;
481  }
482  }
483  if (st_get_key(loading_tbl, (st_data_t)feature, &data)) {
484  if (fn) *fn = (const char*)data;
485  loading:
486  if (!ext) return 'u';
487  return !IS_RBEXT(ext) ? 's' : 'r';
488  }
489  else {
490  VALUE bufstr;
491  char *buf;
492  static const char so_ext[][4] = {
493  ".so", ".o",
494  };
495 
496  if (ext && *ext) return 0;
497  bufstr = rb_str_tmp_new(len + DLEXT_MAXLEN);
498  buf = RSTRING_PTR(bufstr);
499  MEMCPY(buf, feature, char, len);
500  for (i = 0; (e = loadable_ext[i]) != 0; i++) {
501  strlcpy(buf + len, e, DLEXT_MAXLEN + 1);
502  if (st_get_key(loading_tbl, (st_data_t)buf, &data)) {
503  rb_str_resize(bufstr, 0);
504  if (fn) *fn = (const char*)data;
505  return i ? 's' : 'r';
506  }
507  }
508  for (i = 0; i < numberof(so_ext); i++) {
509  strlcpy(buf + len, so_ext[i], DLEXT_MAXLEN + 1);
510  if (st_get_key(loading_tbl, (st_data_t)buf, &data)) {
511  rb_str_resize(bufstr, 0);
512  if (fn) *fn = (const char*)data;
513  return 's';
514  }
515  }
516  rb_str_resize(bufstr, 0);
517  }
518  }
519  return 0;
520 }
521 
522 int
523 rb_provided(const char *feature)
524 {
525  return rb_feature_provided(feature, 0);
526 }
527 
528 int
529 rb_feature_provided(const char *feature, const char **loading)
530 {
531  const char *ext = strrchr(feature, '.');
532  volatile VALUE fullpath = 0;
533 
534  if (*feature == '.' &&
535  (feature[1] == '/' || strncmp(feature+1, "./", 2) == 0)) {
536  fullpath = rb_file_expand_path_fast(rb_get_path(rb_str_new2(feature)), Qnil);
537  feature = RSTRING_PTR(fullpath);
538  }
539  if (ext && !strchr(ext, '/')) {
540  if (IS_RBEXT(ext)) {
541  if (rb_feature_p(feature, ext, TRUE, FALSE, loading)) return TRUE;
542  return FALSE;
543  }
544  else if (IS_SOEXT(ext) || IS_DLEXT(ext)) {
545  if (rb_feature_p(feature, ext, FALSE, FALSE, loading)) return TRUE;
546  return FALSE;
547  }
548  }
549  if (rb_feature_p(feature, 0, TRUE, FALSE, loading))
550  return TRUE;
551  return FALSE;
552 }
553 
554 static void
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;
687 
688  rb_scan_args(argc, argv, "11", &fname, &wrap);
689 
692  rb_sourcefile(),
693  rb_sourceline());
694  }
695 
696  path = rb_find_file(FilePathValue(fname));
697  if (!path) {
698  if (!rb_file_load_ok(RSTRING_PTR(fname)))
699  load_failed(fname);
700  path = fname;
701  }
702  rb_load_internal(path, RTEST(wrap));
703 
706  rb_sourcefile(),
707  rb_sourceline());
708  }
709 
710  return Qtrue;
711 }
712 
713 static char *
714 load_lock(const char *ftptr)
715 {
716  st_data_t data;
717  st_table *loading_tbl = get_loading_table();
718 
719  if (!loading_tbl || !st_lookup(loading_tbl, (st_data_t)ftptr, &data)) {
720  /* loading ruby library should be serialized. */
721  if (!loading_tbl) {
722  GET_VM()->loading_table = loading_tbl = st_init_strtable();
723  }
724  /* partial state */
725  ftptr = ruby_strdup(ftptr);
727  st_insert(loading_tbl, (st_data_t)ftptr, data);
728  return (char *)ftptr;
729  }
730  else if (RB_TYPE_P((VALUE)data, T_NODE) && nd_type((VALUE)data) == NODE_MEMO) {
731  NODE *memo = RNODE(data);
732  void (*init)(void) = (void (*)(void))memo->nd_cfnc;
734  st_insert(loading_tbl, (st_data_t)ftptr, data);
735  (*init)();
736  return (char *)"";
737  }
738  if (RTEST(ruby_verbose)) {
739  rb_warning("loading in progress, circular require considered harmful - %s", ftptr);
741  }
742  switch (rb_thread_shield_wait((VALUE)data)) {
743  case Qfalse:
744  data = (st_data_t)ftptr;
745  st_insert(loading_tbl, data, (st_data_t)rb_thread_shield_new());
746  return 0;
747  case Qnil:
748  return 0;
749  }
750  return (char *)ftptr;
751 }
752 
753 static int
755 {
756  VALUE thread_shield = (VALUE)*value;
757  if (!existing) return ST_STOP;
758  if (done ? rb_thread_shield_destroy(thread_shield) : rb_thread_shield_release(thread_shield)) {
759  /* still in-use */
760  return ST_CONTINUE;
761  }
762  xfree((char *)*key);
763  return ST_DELETE;
764 }
765 
766 static void
767 load_unlock(const char *ftptr, int done)
768 {
769  if (ftptr) {
770  st_data_t key = (st_data_t)ftptr;
771  st_table *loading_tbl = get_loading_table();
772 
773  st_update(loading_tbl, key, release_thread_shield, done);
774  }
775 }
776 
777 
778 /*
779  * call-seq:
780  * require(name) -> true or false
781  *
782  * Loads the given +name+, returning +true+ if successful and +false+ if the
783  * feature is already loaded.
784  *
785  * If the filename does not resolve to an absolute path, it will be searched
786  * for in the directories listed in <code>$LOAD_PATH</code> (<code>$:</code>).
787  *
788  * If the filename has the extension ".rb", it is loaded as a source file; if
789  * the extension is ".so", ".o", or ".dll", or the default shared library
790  * extension on the current platform, Ruby loads the shared library as a
791  * Ruby extension. Otherwise, Ruby tries adding ".rb", ".so", and so on
792  * to the name until found. If the file named cannot be found, a LoadError
793  * will be raised.
794  *
795  * For Ruby extensions the filename given may use any shared library
796  * extension. For example, on Linux the socket extension is "socket.so" and
797  * <code>require 'socket.dll'</code> will load the socket extension.
798  *
799  * The absolute path of the loaded file is added to
800  * <code>$LOADED_FEATURES</code> (<code>$"</code>). A file will not be
801  * loaded again if its path already appears in <code>$"</code>. For example,
802  * <code>require 'a'; require './a'</code> will not load <code>a.rb</code>
803  * again.
804  *
805  * require "my-library.rb"
806  * require "db-driver"
807  *
808  * Any constants or globals within the loaded source file will be available
809  * in the calling program's global namespace. However, local variables will
810  * not be propagated to the loading environment.
811  *
812  */
813 
814 VALUE
816 {
817  return rb_require_safe(fname, rb_safe_level());
818 }
819 
820 /*
821  * call-seq:
822  * require_relative(string) -> true or false
823  *
824  * Ruby tries to load the library named _string_ relative to the requiring
825  * file's path. If the file's path cannot be determined a LoadError is raised.
826  * If a file is loaded +true+ is returned and false otherwise.
827  */
828 VALUE
830 {
832  if (NIL_P(base)) {
833  rb_loaderror("cannot infer basepath");
834  }
835  base = rb_file_dirname(base);
836  return rb_require_safe(rb_file_absolute_path(fname, base), rb_safe_level());
837 }
838 
839 static int
840 search_required(VALUE fname, volatile VALUE *path, int safe_level)
841 {
842  VALUE tmp;
843  char *ext, *ftptr;
844  int type, ft = 0;
845  const char *loading;
846 
847  *path = 0;
848  ext = strrchr(ftptr = RSTRING_PTR(fname), '.');
849  if (ext && !strchr(ext, '/')) {
850  if (IS_RBEXT(ext)) {
851  if (rb_feature_p(ftptr, ext, TRUE, FALSE, &loading)) {
852  if (loading) *path = rb_filesystem_str_new_cstr(loading);
853  return 'r';
854  }
855  if ((tmp = rb_find_file_safe(fname, safe_level)) != 0) {
856  ext = strrchr(ftptr = RSTRING_PTR(tmp), '.');
857  if (!rb_feature_p(ftptr, ext, TRUE, TRUE, &loading) || loading)
858  *path = tmp;
859  return 'r';
860  }
861  return 0;
862  }
863  else if (IS_SOEXT(ext)) {
864  if (rb_feature_p(ftptr, ext, FALSE, FALSE, &loading)) {
865  if (loading) *path = rb_filesystem_str_new_cstr(loading);
866  return 's';
867  }
868  tmp = rb_str_subseq(fname, 0, ext - RSTRING_PTR(fname));
869 #ifdef DLEXT2
870  OBJ_FREEZE(tmp);
871  if (rb_find_file_ext_safe(&tmp, loadable_ext + 1, safe_level)) {
872  ext = strrchr(ftptr = RSTRING_PTR(tmp), '.');
873  if (!rb_feature_p(ftptr, ext, FALSE, TRUE, &loading) || loading)
874  *path = tmp;
875  return 's';
876  }
877 #else
878  rb_str_cat2(tmp, DLEXT);
879  OBJ_FREEZE(tmp);
880  if ((tmp = rb_find_file_safe(tmp, safe_level)) != 0) {
881  ext = strrchr(ftptr = RSTRING_PTR(tmp), '.');
882  if (!rb_feature_p(ftptr, ext, FALSE, TRUE, &loading) || loading)
883  *path = tmp;
884  return 's';
885  }
886 #endif
887  }
888  else if (IS_DLEXT(ext)) {
889  if (rb_feature_p(ftptr, ext, FALSE, FALSE, &loading)) {
890  if (loading) *path = rb_filesystem_str_new_cstr(loading);
891  return 's';
892  }
893  if ((tmp = rb_find_file_safe(fname, safe_level)) != 0) {
894  ext = strrchr(ftptr = RSTRING_PTR(tmp), '.');
895  if (!rb_feature_p(ftptr, ext, FALSE, TRUE, &loading) || loading)
896  *path = tmp;
897  return 's';
898  }
899  }
900  }
901  else if ((ft = rb_feature_p(ftptr, 0, FALSE, FALSE, &loading)) == 'r') {
902  if (loading) *path = rb_filesystem_str_new_cstr(loading);
903  return 'r';
904  }
905  tmp = fname;
906  type = rb_find_file_ext_safe(&tmp, loadable_ext, safe_level);
907  switch (type) {
908  case 0:
909  if (ft)
910  goto statically_linked;
911  ftptr = RSTRING_PTR(tmp);
912  return rb_feature_p(ftptr, 0, FALSE, TRUE, 0);
913 
914  default:
915  if (ft) {
916  statically_linked:
917  if (loading) *path = rb_filesystem_str_new_cstr(loading);
918  return ft;
919  }
920  case 1:
921  ext = strrchr(ftptr = RSTRING_PTR(tmp), '.');
922  if (rb_feature_p(ftptr, ext, !--type, TRUE, &loading) && !loading)
923  break;
924  *path = tmp;
925  }
926  return type ? 's' : 'r';
927 }
928 
929 static void
931 {
932  rb_load_fail(fname, "cannot load such file");
933 }
934 
935 static VALUE
937 {
939  return (VALUE)dln_load(RSTRING_PTR(path));
940 }
941 
942 VALUE
943 rb_require_safe(VALUE fname, int safe)
944 {
945  volatile VALUE result = Qnil;
946  rb_thread_t *th = GET_THREAD();
947  volatile VALUE errinfo = th->errinfo;
948  int state;
949  struct {
950  int safe;
951  } volatile saved;
952  char *volatile ftptr = 0;
953 
956  rb_sourcefile(),
957  rb_sourceline());
958  }
959 
960  PUSH_TAG();
961  saved.safe = rb_safe_level();
962  if ((state = EXEC_TAG()) == 0) {
963  VALUE path;
964  long handle;
965  int found;
966 
968  FilePathValue(fname);
970 
973  rb_sourcefile(),
974  rb_sourceline());
975  }
976 
977  path = rb_str_encode_ospath(fname);
978  found = search_required(path, &path, safe);
979 
982  rb_sourcefile(),
983  rb_sourceline());
984  }
985  if (found) {
986  if (!path || !(ftptr = load_lock(RSTRING_PTR(path)))) {
987  result = Qfalse;
988  }
989  else if (!*ftptr) {
990  rb_provide_feature(path);
991  result = Qtrue;
992  }
993  else {
994  switch (found) {
995  case 'r':
996  rb_load_internal(path, 0);
997  break;
998 
999  case 's':
1000  handle = (long)rb_vm_call_cfunc(rb_vm_top_self(), load_ext,
1001  path, 0, path);
1003  break;
1004  }
1005  rb_provide_feature(path);
1006  result = Qtrue;
1007  }
1008  }
1009  }
1010  POP_TAG();
1011  load_unlock(ftptr, !state);
1012 
1013  rb_set_safe_level_force(saved.safe);
1014  if (state) {
1015  JUMP_TAG(state);
1016  }
1017 
1018  if (NIL_P(result)) {
1019  load_failed(fname);
1020  }
1021 
1022  th->errinfo = errinfo;
1023 
1026  rb_sourcefile(),
1027  rb_sourceline());
1028  }
1029 
1030  return result;
1031 }
1032 
1033 VALUE
1034 rb_require(const char *fname)
1035 {
1036  VALUE fn = rb_str_new2(fname);
1037  OBJ_FREEZE(fn);
1038  return rb_require_safe(fn, rb_safe_level());
1039 }
1040 
1041 static int
1042 register_init_ext(st_data_t *key, st_data_t *value, st_data_t init, int existing)
1043 {
1044  const char *name = (char *)*key;
1045  if (existing) {
1046  /* already registered */
1047  rb_warn("%s is already registered", name);
1048  }
1049  else {
1050  *value = (st_data_t)NEW_MEMO(init, 0, 0);
1051  *key = (st_data_t)ruby_strdup(name);
1052  }
1053  return ST_CONTINUE;
1054 }
1055 
1056 RUBY_FUNC_EXPORTED void
1057 ruby_init_ext(const char *name, void (*init)(void))
1058 {
1059  st_table *loading_tbl = get_loading_table();
1060 
1061  if (!loading_tbl) {
1062  GET_VM()->loading_table = loading_tbl = st_init_strtable();
1063  }
1064  st_update(loading_tbl, (st_data_t)name, register_init_ext, (st_data_t)init);
1065 }
1066 
1067 /*
1068  * call-seq:
1069  * mod.autoload(module, filename) -> nil
1070  *
1071  * Registers _filename_ to be loaded (using <code>Kernel::require</code>)
1072  * the first time that _module_ (which may be a <code>String</code> or
1073  * a symbol) is accessed in the namespace of _mod_.
1074  *
1075  * module A
1076  * end
1077  * A.autoload(:B, "b")
1078  * A::B.doit # autoloads "b"
1079  */
1080 
1081 static VALUE
1083 {
1084  ID id = rb_to_id(sym);
1085 
1086  FilePathValue(file);
1087  rb_autoload(mod, id, RSTRING_PTR(file));
1088  return Qnil;
1089 }
1090 
1091 /*
1092  * call-seq:
1093  * mod.autoload?(name) -> String or nil
1094  *
1095  * Returns _filename_ to be loaded if _name_ is registered as
1096  * +autoload+ in the namespace of _mod_.
1097  *
1098  * module A
1099  * end
1100  * A.autoload(:B, "b")
1101  * A.autoload?(:B) #=> "b"
1102  */
1103 
1104 static VALUE
1106 {
1107  ID id = rb_check_id(&sym);
1108  if (!id) {
1109  return Qnil;
1110  }
1111  return rb_autoload_p(mod, id);
1112 }
1113 
1114 /*
1115  * call-seq:
1116  * autoload(module, filename) -> nil
1117  *
1118  * Registers _filename_ to be loaded (using <code>Kernel::require</code>)
1119  * the first time that _module_ (which may be a <code>String</code> or
1120  * a symbol) is accessed.
1121  *
1122  * autoload(:MyModule, "/usr/local/lib/modules/my_module.rb")
1123  */
1124 
1125 static VALUE
1127 {
1128  VALUE klass = rb_class_real(rb_vm_cbase());
1129  if (NIL_P(klass)) {
1130  rb_raise(rb_eTypeError, "Can not set autoload on singleton class");
1131  }
1132  return rb_mod_autoload(klass, sym, file);
1133 }
1134 
1135 /*
1136  * call-seq:
1137  * autoload?(name) -> String or nil
1138  *
1139  * Returns _filename_ to be loaded if _name_ is registered as
1140  * +autoload+.
1141  *
1142  * autoload(:B, "b")
1143  * autoload?(:B) #=> "b"
1144  */
1145 
1146 static VALUE
1148 {
1149  /* use rb_vm_cbase() as same as rb_f_autoload. */
1150  VALUE klass = rb_vm_cbase();
1151  if (NIL_P(klass)) {
1152  return Qnil;
1153  }
1154  return rb_mod_autoload_p(klass, sym);
1155 }
1156 
1157 void
1159 {
1160 #undef rb_intern
1161 #define rb_intern(str) rb_intern2((str), strlen(str))
1162  rb_vm_t *vm = GET_VM();
1163  static const char var_load_path[] = "$:";
1164  ID id_load_path = rb_intern2(var_load_path, sizeof(var_load_path)-1);
1165 
1167  rb_alias_variable(rb_intern("$-I"), id_load_path);
1168  rb_alias_variable(rb_intern("$LOAD_PATH"), id_load_path);
1169  vm->load_path = rb_ary_new();
1172  vm->load_path_check_cache = 0;
1173 
1175  rb_define_virtual_variable("$LOADED_FEATURES", get_loaded_features, 0);
1176  vm->loaded_features = rb_ary_new();
1179 
1180  rb_define_global_function("load", rb_f_load, -1);
1181  rb_define_global_function("require", rb_f_require, 1);
1182  rb_define_global_function("require_relative", rb_f_require_relative, 1);
1183  rb_define_method(rb_cModule, "autoload", rb_mod_autoload, 2);
1184  rb_define_method(rb_cModule, "autoload?", rb_mod_autoload_p, 1);
1185  rb_define_global_function("autoload", rb_f_autoload, 2);
1186  rb_define_global_function("autoload?", rb_f_autoload_p, 1);
1187 
1190 }
1191