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