Ruby  2.7.1p83(2020-03-31revisiona0c7c23c9cec0d0ffcba012279cd652d28ad5bf3)
load.c
Go to the documentation of this file.
1 /*
2  * load methods from eval.c
3  */
4 
5 #include "ruby/encoding.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 "iseq.h"
12 
13 static VALUE ruby_dln_librefs;
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 
36 };
37 
38 /* Construct expanded load path and store it to cache.
39  We rebuild load path partially if the cache is invalid.
40  We don't cache non string object and expand it every time. We ensure that
41  string objects in $LOAD_PATH are frozen.
42  */
43 static void
44 rb_construct_expanded_load_path(enum expand_type type, int *has_relative, int *has_non_cache)
45 {
46  rb_vm_t *vm = GET_VM();
47  VALUE load_path = vm->load_path;
48  VALUE expanded_load_path = vm->expanded_load_path;
49  VALUE ary;
50  long i;
51 
52  ary = rb_ary_tmp_new(RARRAY_LEN(load_path));
53  for (i = 0; i < RARRAY_LEN(load_path); ++i) {
54  VALUE path, as_str, expanded_path;
55  int is_string, non_cache;
56  char *as_cstr;
57  as_str = path = RARRAY_AREF(load_path, i);
58  is_string = RB_TYPE_P(path, T_STRING) ? 1 : 0;
59  non_cache = !is_string ? 1 : 0;
61  as_cstr = RSTRING_PTR(as_str);
62 
63  if (!non_cache) {
64  if ((type == EXPAND_RELATIVE &&
65  rb_is_absolute_path(as_cstr)) ||
66  (type == EXPAND_HOME &&
67  (!as_cstr[0] || as_cstr[0] != '~')) ||
68  (type == EXPAND_NON_CACHE)) {
69  /* Use cached expanded path. */
70  rb_ary_push(ary, RARRAY_AREF(expanded_load_path, i));
71  continue;
72  }
73  }
74  if (!*has_relative && !rb_is_absolute_path(as_cstr))
75  *has_relative = 1;
76  if (!*has_non_cache && non_cache)
77  *has_non_cache = 1;
78  /* Freeze only string object. We expand other objects every time. */
79  if (is_string)
81  as_str = rb_get_path_check_convert(as_str);
82  expanded_path = rb_check_realpath(Qnil, as_str, NULL);
83  if (NIL_P(expanded_path)) expanded_path = as_str;
84  rb_ary_push(ary, rb_fstring(expanded_path));
85  }
86  rb_obj_freeze(ary);
87  vm->expanded_load_path = ary;
89 }
90 
91 VALUE
93 {
94  rb_vm_t *vm = GET_VM();
95  const VALUE non_cache = Qtrue;
96 
98  /* The load path was modified. Rebuild the expanded load path. */
99  int has_relative = 0, has_non_cache = 0;
100  rb_construct_expanded_load_path(EXPAND_ALL, &has_relative, &has_non_cache);
101  if (has_relative) {
103  }
104  else if (has_non_cache) {
105  /* Non string object. */
106  vm->load_path_check_cache = non_cache;
107  }
108  else {
109  vm->load_path_check_cache = 0;
110  }
111  }
112  else if (vm->load_path_check_cache == non_cache) {
113  int has_relative = 1, has_non_cache = 1;
114  /* Expand only non-cacheable objects. */
115  rb_construct_expanded_load_path(EXPAND_NON_CACHE,
116  &has_relative, &has_non_cache);
117  }
118  else if (vm->load_path_check_cache) {
119  int has_relative = 1, has_non_cache = 1;
120  VALUE cwd = rb_dir_getwd_ospath();
121  if (!rb_str_equal(vm->load_path_check_cache, cwd)) {
122  /* Current working directory or filesystem encoding was changed.
123  Expand relative load path and non-cacheable objects again. */
124  vm->load_path_check_cache = cwd;
125  rb_construct_expanded_load_path(EXPAND_RELATIVE,
126  &has_relative, &has_non_cache);
127  }
128  else {
129  /* Expand only tilde (User HOME) and non-cacheable objects. */
130  rb_construct_expanded_load_path(EXPAND_HOME,
131  &has_relative, &has_non_cache);
132  }
133  }
134  return vm->expanded_load_path;
135 }
136 
137 static VALUE
138 load_path_getter(ID id, VALUE * p)
139 {
140  rb_vm_t *vm = (void *)p;
141  return vm->load_path;
142 }
143 
144 static VALUE
145 get_loaded_features(void)
146 {
147  return GET_VM()->loaded_features;
148 }
149 
150 static VALUE
151 get_LOADED_FEATURES(ID _x, VALUE *_y)
152 {
153  return get_loaded_features();
154 }
155 
156 static void
157 reset_loaded_features_snapshot(void)
158 {
159  rb_vm_t *vm = GET_VM();
161 }
162 
163 static struct st_table *
164 get_loaded_features_index_raw(void)
165 {
166  return GET_VM()->loaded_features_index;
167 }
168 
169 static st_table *
170 get_loading_table(void)
171 {
172  return GET_VM()->loading_table;
173 }
174 
175 static st_data_t
176 feature_key(const char *str, size_t len)
177 {
178  return st_hash(str, len, 0xfea7009e);
179 }
180 
181 static void
182 features_index_add_single(const char* str, size_t len, VALUE offset)
183 {
184  struct st_table *features_index;
185  VALUE this_feature_index = Qnil;
186  st_data_t short_feature_key;
187 
188  Check_Type(offset, T_FIXNUM);
189  short_feature_key = feature_key(str, len);
190 
191  features_index = get_loaded_features_index_raw();
192  st_lookup(features_index, short_feature_key, (st_data_t *)&this_feature_index);
193 
194  if (NIL_P(this_feature_index)) {
195  st_insert(features_index, short_feature_key, (st_data_t)offset);
196  }
197  else if (RB_TYPE_P(this_feature_index, T_FIXNUM)) {
198  VALUE feature_indexes[2];
199  feature_indexes[0] = this_feature_index;
200  feature_indexes[1] = offset;
201  this_feature_index = (VALUE)xcalloc(1, sizeof(struct RArray));
202  RBASIC(this_feature_index)->flags = T_ARRAY; /* fake VALUE, do not mark/sweep */
203  rb_ary_cat(this_feature_index, feature_indexes, numberof(feature_indexes));
204  st_insert(features_index, short_feature_key, (st_data_t)this_feature_index);
205  }
206  else {
207  Check_Type(this_feature_index, T_ARRAY);
208  rb_ary_push(this_feature_index, offset);
209  }
210 }
211 
212 /* Add to the loaded-features index all the required entries for
213  `feature`, located at `offset` in $LOADED_FEATURES. We add an
214  index entry at each string `short_feature` for which
215  feature == "#{prefix}#{short_feature}#{ext}"
216  where `ext` is empty or matches %r{^\.[^./]*$}, and `prefix` is empty
217  or ends in '/'. This maintains the invariant that `rb_feature_p()`
218  relies on for its fast lookup.
219 */
220 static void
221 features_index_add(VALUE feature, VALUE offset)
222 {
223  const char *feature_str, *feature_end, *ext, *p;
224 
225  feature_str = StringValuePtr(feature);
226  feature_end = feature_str + RSTRING_LEN(feature);
227 
228  for (ext = feature_end; ext > feature_str; ext--)
229  if (*ext == '.' || *ext == '/')
230  break;
231  if (*ext != '.')
232  ext = NULL;
233  /* Now `ext` points to the only string matching %r{^\.[^./]*$} that is
234  at the end of `feature`, or is NULL if there is no such string. */
235 
236  p = ext ? ext : feature_end;
237  while (1) {
238  p--;
239  while (p >= feature_str && *p != '/')
240  p--;
241  if (p < feature_str)
242  break;
243  /* Now *p == '/'. We reach this point for every '/' in `feature`. */
244  features_index_add_single(p + 1, feature_end - p - 1, offset);
245  if (ext) {
246  features_index_add_single(p + 1, ext - p - 1, offset);
247  }
248  }
249  features_index_add_single(feature_str, feature_end - feature_str, offset);
250  if (ext) {
251  features_index_add_single(feature_str, ext - feature_str, offset);
252  }
253 }
254 
255 static int
256 loaded_features_index_clear_i(st_data_t key, st_data_t val, st_data_t arg)
257 {
258  VALUE obj = (VALUE)val;
259  if (!SPECIAL_CONST_P(obj)) {
260  rb_ary_free(obj);
261  ruby_sized_xfree((void *)obj, sizeof(struct RArray));
262  }
263  return ST_DELETE;
264 }
265 
266 static st_table *
267 get_loaded_features_index(void)
268 {
269  VALUE features;
270  int i;
271  rb_vm_t *vm = GET_VM();
272 
274  /* The sharing was broken; something (other than us in rb_provide_feature())
275  modified loaded_features. Rebuild the index. */
276  st_foreach(vm->loaded_features_index, loaded_features_index_clear_i, 0);
277  features = vm->loaded_features;
278  for (i = 0; i < RARRAY_LEN(features); i++) {
279  VALUE entry, as_str;
280  as_str = entry = rb_ary_entry(features, i);
281  StringValue(as_str);
282  as_str = rb_fstring(rb_str_freeze(as_str));
283  if (as_str != entry)
284  rb_ary_store(features, i, as_str);
285  features_index_add(as_str, INT2FIX(i));
286  }
287  reset_loaded_features_snapshot();
288  }
289  return vm->loaded_features_index;
290 }
291 
292 /* This searches `load_path` for a value such that
293  name == "#{load_path[i]}/#{feature}"
294  if `feature` is a suffix of `name`, or otherwise
295  name == "#{load_path[i]}/#{feature}#{ext}"
296  for an acceptable string `ext`. It returns
297  `load_path[i].to_str` if found, else 0.
298 
299  If type is 's', then `ext` is acceptable only if IS_DLEXT(ext);
300  if 'r', then only if IS_RBEXT(ext); otherwise `ext` may be absent
301  or have any value matching `%r{^\.[^./]*$}`.
302 */
303 static VALUE
304 loaded_feature_path(const char *name, long vlen, const char *feature, long len,
305  int type, VALUE load_path)
306 {
307  long i;
308  long plen;
309  const char *e;
310 
311  if (vlen < len+1) return 0;
312  if (strchr(feature, '.') && !strncmp(name+(vlen-len), feature, len)) {
313  plen = vlen - len;
314  }
315  else {
316  for (e = name + vlen; name != e && *e != '.' && *e != '/'; --e);
317  if (*e != '.' ||
318  e-name < len ||
319  strncmp(e-len, feature, len))
320  return 0;
321  plen = e - name - len;
322  }
323  if (plen > 0 && name[plen-1] != '/') {
324  return 0;
325  }
326  if (type == 's' ? !IS_DLEXT(&name[plen+len]) :
327  type == 'r' ? !IS_RBEXT(&name[plen+len]) :
328  0) {
329  return 0;
330  }
331  /* Now name == "#{prefix}/#{feature}#{ext}" where ext is acceptable
332  (possibly empty) and prefix is some string of length plen. */
333 
334  if (plen > 0) --plen; /* exclude '.' */
335  for (i = 0; i < RARRAY_LEN(load_path); ++i) {
336  VALUE p = RARRAY_AREF(load_path, i);
337  const char *s = StringValuePtr(p);
338  long n = RSTRING_LEN(p);
339 
340  if (n != plen) continue;
341  if (n && strncmp(name, s, n)) continue;
342  return p;
343  }
344  return 0;
345 }
346 
348  const char *name;
349  long len;
350  int type;
352  const char *result;
353 };
354 
355 static int
356 loaded_feature_path_i(st_data_t v, st_data_t b, st_data_t f)
357 {
358  const char *s = (const char *)v;
359  struct loaded_feature_searching *fp = (struct loaded_feature_searching *)f;
360  VALUE p = loaded_feature_path(s, strlen(s), fp->name, fp->len,
361  fp->type, fp->load_path);
362  if (!p) return ST_CONTINUE;
363  fp->result = s;
364  return ST_STOP;
365 }
366 
367 static int
368 rb_feature_p(const char *feature, const char *ext, int rb, int expanded, const char **fn)
369 {
370  VALUE features, this_feature_index = Qnil, v, p, load_path = 0;
371  const char *f, *e;
372  long i, len, elen, n;
373  st_table *loading_tbl, *features_index;
374  st_data_t data;
375  st_data_t key;
376  int type;
377 
378  if (fn) *fn = 0;
379  if (ext) {
380  elen = strlen(ext);
381  len = strlen(feature) - elen;
382  type = rb ? 'r' : 's';
383  }
384  else {
385  len = strlen(feature);
386  elen = 0;
387  type = 0;
388  }
389  features = get_loaded_features();
390  features_index = get_loaded_features_index();
391 
392  key = feature_key(feature, strlen(feature));
393  st_lookup(features_index, key, (st_data_t *)&this_feature_index);
394  /* We search `features` for an entry such that either
395  "#{features[i]}" == "#{load_path[j]}/#{feature}#{e}"
396  for some j, or
397  "#{features[i]}" == "#{feature}#{e}"
398  Here `e` is an "allowed" extension -- either empty or one
399  of the extensions accepted by IS_RBEXT, IS_SOEXT, or
400  IS_DLEXT. Further, if `ext && rb` then `IS_RBEXT(e)`,
401  and if `ext && !rb` then `IS_SOEXT(e) || IS_DLEXT(e)`.
402 
403  If `expanded`, then only the latter form (without load_path[j])
404  is accepted. Otherwise either form is accepted, *unless* `ext`
405  is false and an otherwise-matching entry of the first form is
406  preceded by an entry of the form
407  "#{features[i2]}" == "#{load_path[j2]}/#{feature}#{e2}"
408  where `e2` matches %r{^\.[^./]*$} but is not an allowed extension.
409  After a "distractor" entry of this form, only entries of the
410  form "#{feature}#{e}" are accepted.
411 
412  In `rb_provide_feature()` and `get_loaded_features_index()` we
413  maintain an invariant that the array `this_feature_index` will
414  point to every entry in `features` which has the form
415  "#{prefix}#{feature}#{e}"
416  where `e` is empty or matches %r{^\.[^./]*$}, and `prefix` is empty
417  or ends in '/'. This includes both match forms above, as well
418  as any distractors, so we may ignore all other entries in `features`.
419  */
420  if (!NIL_P(this_feature_index)) {
421  for (i = 0; ; i++) {
422  VALUE entry;
423  long index;
424  if (RB_TYPE_P(this_feature_index, T_ARRAY)) {
425  if (i >= RARRAY_LEN(this_feature_index)) break;
426  entry = RARRAY_AREF(this_feature_index, i);
427  }
428  else {
429  if (i > 0) break;
430  entry = this_feature_index;
431  }
432  index = FIX2LONG(entry);
433 
434  v = RARRAY_AREF(features, index);
435  f = StringValuePtr(v);
436  if ((n = RSTRING_LEN(v)) < len) continue;
437  if (strncmp(f, feature, len) != 0) {
438  if (expanded) continue;
440  if (!(p = loaded_feature_path(f, n, feature, len, type, load_path)))
441  continue;
442  expanded = 1;
443  f += RSTRING_LEN(p) + 1;
444  }
445  if (!*(e = f + len)) {
446  if (ext) continue;
447  return 'u';
448  }
449  if (*e != '.') continue;
450  if ((!rb || !ext) && (IS_SOEXT(e) || IS_DLEXT(e))) {
451  return 's';
452  }
453  if ((rb || !ext) && (IS_RBEXT(e))) {
454  return 'r';
455  }
456  }
457  }
458 
459  loading_tbl = get_loading_table();
460  f = 0;
461  if (!expanded) {
462  struct loaded_feature_searching fs;
463  fs.name = feature;
464  fs.len = len;
465  fs.type = type;
466  fs.load_path = load_path ? load_path : rb_get_expanded_load_path();
467  fs.result = 0;
468  st_foreach(loading_tbl, loaded_feature_path_i, (st_data_t)&fs);
469  if ((f = fs.result) != 0) {
470  if (fn) *fn = f;
471  goto loading;
472  }
473  }
474  if (st_get_key(loading_tbl, (st_data_t)feature, &data)) {
475  if (fn) *fn = (const char*)data;
476  loading:
477  if (!ext) return 'u';
478  return !IS_RBEXT(ext) ? 's' : 'r';
479  }
480  else {
481  VALUE bufstr;
482  char *buf;
483  static const char so_ext[][4] = {
484  ".so", ".o",
485  };
486 
487  if (ext && *ext) return 0;
488  bufstr = rb_str_tmp_new(len + DLEXT_MAXLEN);
489  buf = RSTRING_PTR(bufstr);
490  MEMCPY(buf, feature, char, len);
491  for (i = 0; (e = loadable_ext[i]) != 0; i++) {
492  strlcpy(buf + len, e, DLEXT_MAXLEN + 1);
493  if (st_get_key(loading_tbl, (st_data_t)buf, &data)) {
494  rb_str_resize(bufstr, 0);
495  if (fn) *fn = (const char*)data;
496  return i ? 's' : 'r';
497  }
498  }
499  for (i = 0; i < numberof(so_ext); i++) {
500  strlcpy(buf + len, so_ext[i], DLEXT_MAXLEN + 1);
501  if (st_get_key(loading_tbl, (st_data_t)buf, &data)) {
502  rb_str_resize(bufstr, 0);
503  if (fn) *fn = (const char*)data;
504  return 's';
505  }
506  }
507  rb_str_resize(bufstr, 0);
508  }
509  return 0;
510 }
511 
512 int
513 rb_provided(const char *feature)
514 {
515  return rb_feature_provided(feature, 0);
516 }
517 
518 int
519 rb_feature_provided(const char *feature, const char **loading)
520 {
521  const char *ext = strrchr(feature, '.');
522  VALUE fullpath = 0;
523 
524  if (*feature == '.' &&
525  (feature[1] == '/' || strncmp(feature+1, "./", 2) == 0)) {
526  fullpath = rb_file_expand_path_fast(rb_get_path(rb_str_new2(feature)), Qnil);
527  feature = RSTRING_PTR(fullpath);
528  }
529  if (ext && !strchr(ext, '/')) {
530  if (IS_RBEXT(ext)) {
531  if (rb_feature_p(feature, ext, TRUE, FALSE, loading)) return TRUE;
532  return FALSE;
533  }
534  else if (IS_SOEXT(ext) || IS_DLEXT(ext)) {
535  if (rb_feature_p(feature, ext, FALSE, FALSE, loading)) return TRUE;
536  return FALSE;
537  }
538  }
539  if (rb_feature_p(feature, 0, TRUE, FALSE, loading))
540  return TRUE;
541  RB_GC_GUARD(fullpath);
542  return FALSE;
543 }
544 
545 static void
546 rb_provide_feature(VALUE feature)
547 {
548  VALUE features;
549 
550  features = get_loaded_features();
551  if (OBJ_FROZEN(features)) {
553  "$LOADED_FEATURES is frozen; cannot append feature");
554  }
555  rb_str_freeze(feature);
556 
557  rb_ary_push(features, rb_fstring(feature));
558  features_index_add(feature, INT2FIX(RARRAY_LEN(features)-1));
559  reset_loaded_features_snapshot();
560 }
561 
562 void
563 rb_provide(const char *feature)
564 {
565  rb_provide_feature(rb_fstring_cstr(feature));
566 }
567 
568 NORETURN(static void load_failed(VALUE));
569 
570 static inline void
571 load_iseq_eval(rb_execution_context_t *ec, VALUE fname)
572 {
573  const rb_iseq_t *iseq = rb_iseq_load_iseq(fname);
574 
575  if (!iseq) {
576  rb_ast_t *ast;
577  VALUE parser = rb_parser_new();
578  rb_parser_set_context(parser, NULL, FALSE);
579  ast = (rb_ast_t *)rb_parser_load_file(parser, fname);
580  iseq = rb_iseq_new_top(&ast->body, rb_fstring_lit("<top (required)>"),
581  fname, rb_realpath_internal(Qnil, fname, 1), NULL);
582  rb_ast_dispose(ast);
583  }
584  rb_exec_event_hook_script_compiled(ec, iseq, Qnil);
586 }
587 
588 static inline enum ruby_tag_type
589 load_wrapping(rb_execution_context_t *ec, VALUE fname)
590 {
591  enum ruby_tag_type state;
592  rb_thread_t *th = rb_ec_thread_ptr(ec);
593  volatile VALUE wrapper = th->top_wrapper;
594  volatile VALUE self = th->top_self;
595 #if !defined __GNUC__
596  rb_thread_t *volatile th0 = th;
597 #endif
598 
599  ec->errinfo = Qnil; /* ensure */
600 
601  /* load in anonymous module as toplevel */
603  th->top_wrapper = rb_module_new();
605 
606  EC_PUSH_TAG(ec);
607  state = EC_EXEC_TAG();
608  if (state == TAG_NONE) {
609  load_iseq_eval(ec, fname);
610  }
611  EC_POP_TAG();
612 
613 #if !defined __GNUC__
614  th = th0;
615  fname = RB_GC_GUARD(fname);
616 #endif
617  th->top_self = self;
618  th->top_wrapper = wrapper;
619  return state;
620 }
621 
622 static inline void
623 raise_load_if_failed(rb_execution_context_t *ec, enum ruby_tag_type state)
624 {
625  if (state) {
627  }
628 
629  if (!NIL_P(ec->errinfo)) {
630  rb_exc_raise(ec->errinfo);
631  }
632 }
633 
634 static void
635 rb_load_internal(VALUE fname, int wrap)
636 {
638  enum ruby_tag_type state = TAG_NONE;
639  if (wrap) {
640  state = load_wrapping(ec, fname);
641  }
642  else {
643  load_iseq_eval(ec, fname);
644  }
645  raise_load_if_failed(ec, state);
646 }
647 
648 void
649 rb_load(VALUE fname, int wrap)
650 {
651  VALUE tmp = rb_find_file(FilePathValue(fname));
652  if (!tmp) load_failed(fname);
653  rb_load_internal(tmp, wrap);
654 }
655 
656 void
657 rb_load_protect(VALUE fname, int wrap, int *pstate)
658 {
659  enum ruby_tag_type state;
660 
661  EC_PUSH_TAG(GET_EC());
662  if ((state = EC_EXEC_TAG()) == TAG_NONE) {
663  rb_load(fname, wrap);
664  }
665  EC_POP_TAG();
666 
667  if (state != TAG_NONE) *pstate = state;
668 }
669 
670 /*
671  * call-seq:
672  * load(filename, wrap=false) -> true
673  *
674  * Loads and executes the Ruby
675  * program in the file _filename_. If the filename does not
676  * resolve to an absolute path, the file is searched for in the library
677  * directories listed in <code>$:</code>. If the optional _wrap_
678  * parameter is +true+, the loaded script will be executed
679  * under an anonymous module, protecting the calling program's global
680  * namespace. In no circumstance will any local variables in the loaded
681  * file be propagated to the loading environment.
682  */
683 
684 static VALUE
685 rb_f_load(int argc, VALUE *argv, VALUE _)
686 {
687  VALUE fname, wrap, path, orig_fname;
688 
689  rb_scan_args(argc, argv, "11", &fname, &wrap);
690 
691  orig_fname = rb_get_path_check_to_string(fname);
692  fname = rb_str_encode_ospath(orig_fname);
693  RUBY_DTRACE_HOOK(LOAD_ENTRY, RSTRING_PTR(orig_fname));
694 
695  path = rb_find_file(fname);
696  if (!path) {
697  if (!rb_file_load_ok(RSTRING_PTR(fname)))
698  load_failed(orig_fname);
699  path = fname;
700  }
701  rb_load_internal(path, RTEST(wrap));
702 
703  RUBY_DTRACE_HOOK(LOAD_RETURN, RSTRING_PTR(orig_fname));
704 
705  return Qtrue;
706 }
707 
708 static char *
709 load_lock(const char *ftptr)
710 {
711  st_data_t data;
712  st_table *loading_tbl = get_loading_table();
713 
714  if (!st_lookup(loading_tbl, (st_data_t)ftptr, &data)) {
715  /* partial state */
716  ftptr = ruby_strdup(ftptr);
718  st_insert(loading_tbl, (st_data_t)ftptr, data);
719  return (char *)ftptr;
720  }
721  else if (imemo_type_p(data, imemo_memo)) {
722  struct MEMO *memo = MEMO_CAST(data);
723  void (*init)(void) = memo->u3.func;
725  st_insert(loading_tbl, (st_data_t)ftptr, data);
726  (*init)();
727  return (char *)"";
728  }
729  if (RTEST(ruby_verbose)) {
730  VALUE warning = rb_warning_string("loading in progress, circular require considered harmful - %s", ftptr);
732  rb_warning("%"PRIsVALUE, warning);
733  }
734  switch (rb_thread_shield_wait((VALUE)data)) {
735  case Qfalse:
736  case Qnil:
737  return 0;
738  }
739  return (char *)ftptr;
740 }
741 
742 static int
743 release_thread_shield(st_data_t *key, st_data_t *value, st_data_t done, int existing)
744 {
745  VALUE thread_shield = (VALUE)*value;
746  if (!existing) return ST_STOP;
747  if (done) {
748  rb_thread_shield_destroy(thread_shield);
749  /* Delete the entry even if there are waiting threads, because they
750  * won't load the file and won't delete the entry. */
751  }
752  else if (rb_thread_shield_release(thread_shield)) {
753  /* still in-use */
754  return ST_CONTINUE;
755  }
756  xfree((char *)*key);
757  return ST_DELETE;
758 }
759 
760 static void
761 load_unlock(const char *ftptr, int done)
762 {
763  if (ftptr) {
764  st_data_t key = (st_data_t)ftptr;
765  st_table *loading_tbl = get_loading_table();
766 
767  st_update(loading_tbl, key, release_thread_shield, done);
768  }
769 }
770 
771 
772 /*
773  * call-seq:
774  * require(name) -> true or false
775  *
776  * Loads the given +name+, returning +true+ if successful and +false+ if the
777  * feature is already loaded.
778  *
779  * If the filename does not resolve to an absolute path, it will be searched
780  * for in the directories listed in <code>$LOAD_PATH</code> (<code>$:</code>).
781  *
782  * If the filename has the extension ".rb", it is loaded as a source file; if
783  * the extension is ".so", ".o", or ".dll", or the default shared library
784  * extension on the current platform, Ruby loads the shared library as a
785  * Ruby extension. Otherwise, Ruby tries adding ".rb", ".so", and so on
786  * to the name until found. If the file named cannot be found, a LoadError
787  * will be raised.
788  *
789  * For Ruby extensions the filename given may use any shared library
790  * extension. For example, on Linux the socket extension is "socket.so" and
791  * <code>require 'socket.dll'</code> will load the socket extension.
792  *
793  * The absolute path of the loaded file is added to
794  * <code>$LOADED_FEATURES</code> (<code>$"</code>). A file will not be
795  * loaded again if its path already appears in <code>$"</code>. For example,
796  * <code>require 'a'; require './a'</code> will not load <code>a.rb</code>
797  * again.
798  *
799  * require "my-library.rb"
800  * require "db-driver"
801  *
802  * Any constants or globals within the loaded source file will be available
803  * in the calling program's global namespace. However, local variables will
804  * not be propagated to the loading environment.
805  *
806  */
807 
808 VALUE
810 {
811  return rb_require_string(fname);
812 }
813 
814 /*
815  * call-seq:
816  * require_relative(string) -> true or false
817  *
818  * Ruby tries to load the library named _string_ relative to the requiring
819  * file's path. If the file's path cannot be determined a LoadError is raised.
820  * If a file is loaded +true+ is returned and false otherwise.
821  */
822 VALUE
824 {
826  if (NIL_P(base)) {
827  rb_loaderror("cannot infer basepath");
828  }
829  base = rb_file_dirname(base);
830  return rb_require_string(rb_file_absolute_path(fname, base));
831 }
832 
833 typedef int (*feature_func)(const char *feature, const char *ext, int rb, int expanded, const char **fn);
834 
835 static int
836 search_required(VALUE fname, volatile VALUE *path, feature_func rb_feature_p)
837 {
838  VALUE tmp;
839  char *ext, *ftptr;
840  int type, ft = 0;
841  const char *loading;
842 
843  *path = 0;
844  ext = strrchr(ftptr = RSTRING_PTR(fname), '.');
845  if (ext && !strchr(ext, '/')) {
846  if (IS_RBEXT(ext)) {
847  if (rb_feature_p(ftptr, ext, TRUE, FALSE, &loading)) {
848  if (loading) *path = rb_filesystem_str_new_cstr(loading);
849  return 'r';
850  }
851  if ((tmp = rb_find_file(fname)) != 0) {
852  ext = strrchr(ftptr = RSTRING_PTR(tmp), '.');
853  if (!rb_feature_p(ftptr, ext, TRUE, TRUE, &loading) || loading)
854  *path = tmp;
855  return 'r';
856  }
857  return 0;
858  }
859  else if (IS_SOEXT(ext)) {
860  if (rb_feature_p(ftptr, ext, FALSE, FALSE, &loading)) {
861  if (loading) *path = rb_filesystem_str_new_cstr(loading);
862  return 's';
863  }
864  tmp = rb_str_subseq(fname, 0, ext - RSTRING_PTR(fname));
865 #ifdef DLEXT2
866  OBJ_FREEZE(tmp);
867  if (rb_find_file_ext(&tmp, loadable_ext + 1)) {
868  ext = strrchr(ftptr = RSTRING_PTR(tmp), '.');
869  if (!rb_feature_p(ftptr, ext, FALSE, TRUE, &loading) || loading)
870  *path = tmp;
871  return 's';
872  }
873 #else
874  rb_str_cat2(tmp, DLEXT);
875  OBJ_FREEZE(tmp);
876  if ((tmp = rb_find_file(tmp)) != 0) {
877  ext = strrchr(ftptr = RSTRING_PTR(tmp), '.');
878  if (!rb_feature_p(ftptr, ext, FALSE, TRUE, &loading) || loading)
879  *path = tmp;
880  return 's';
881  }
882 #endif
883  }
884  else if (IS_DLEXT(ext)) {
885  if (rb_feature_p(ftptr, ext, FALSE, FALSE, &loading)) {
886  if (loading) *path = rb_filesystem_str_new_cstr(loading);
887  return 's';
888  }
889  if ((tmp = rb_find_file(fname)) != 0) {
890  ext = strrchr(ftptr = RSTRING_PTR(tmp), '.');
891  if (!rb_feature_p(ftptr, ext, FALSE, TRUE, &loading) || loading)
892  *path = tmp;
893  return 's';
894  }
895  }
896  }
897  else if ((ft = rb_feature_p(ftptr, 0, FALSE, FALSE, &loading)) == 'r') {
898  if (loading) *path = rb_filesystem_str_new_cstr(loading);
899  return 'r';
900  }
901  tmp = fname;
902  type = rb_find_file_ext(&tmp, loadable_ext);
903  switch (type) {
904  case 0:
905  if (ft)
906  goto statically_linked;
907  ftptr = RSTRING_PTR(tmp);
908  return rb_feature_p(ftptr, 0, FALSE, TRUE, 0);
909 
910  default:
911  if (ft) {
912  statically_linked:
913  if (loading) *path = rb_filesystem_str_new_cstr(loading);
914  return ft;
915  }
916  /* fall through */
917  case 1:
918  ext = strrchr(ftptr = RSTRING_PTR(tmp), '.');
919  if (rb_feature_p(ftptr, ext, !--type, TRUE, &loading) && !loading)
920  break;
921  *path = tmp;
922  }
923  return type ? 's' : 'r';
924 }
925 
926 static void
927 load_failed(VALUE fname)
928 {
929  rb_load_fail(fname, "cannot load such file");
930 }
931 
932 static VALUE
933 load_ext(VALUE path)
934 {
936  return (VALUE)dln_load(RSTRING_PTR(path));
937 }
938 
939 static int
940 no_feature_p(const char *feature, const char *ext, int rb, int expanded, const char **fn)
941 {
942  return 0;
943 }
944 
945 // Documented in doc/globals.rdoc
946 VALUE
948 {
949  VALUE path;
950  int found;
951  VALUE sym;
952 
953  fname = rb_get_path(fname);
954  path = rb_str_encode_ospath(fname);
955  found = search_required(path, &path, no_feature_p);
956 
957  switch (found) {
958  case 'r':
959  sym = ID2SYM(rb_intern("rb"));
960  break;
961  case 's':
962  sym = ID2SYM(rb_intern("so"));
963  break;
964  default:
965  load_failed(fname);
966  }
967 
968  return rb_ary_new_from_args(2, sym, path);
969 }
970 
971 /*
972  * returns
973  * 0: if already loaded (false)
974  * 1: successfully loaded (true)
975  * <0: not found (LoadError)
976  * >1: exception
977  */
978 static int
979 require_internal(rb_execution_context_t *ec, VALUE fname, int exception)
980 {
981  volatile int result = -1;
982  rb_thread_t *th = rb_ec_thread_ptr(ec);
983  volatile VALUE wrapper = th->top_wrapper;
984  volatile VALUE self = th->top_self;
985  volatile VALUE errinfo = ec->errinfo;
986  enum ruby_tag_type state;
987  char *volatile ftptr = 0;
988  VALUE path;
989 
990  fname = rb_get_path(fname);
991  path = rb_str_encode_ospath(fname);
992  RUBY_DTRACE_HOOK(REQUIRE_ENTRY, RSTRING_PTR(fname));
993 
994  EC_PUSH_TAG(ec);
995  ec->errinfo = Qnil; /* ensure */
996  th->top_wrapper = 0;
997  if ((state = EC_EXEC_TAG()) == TAG_NONE) {
998  long handle;
999  int found;
1000 
1001  RUBY_DTRACE_HOOK(FIND_REQUIRE_ENTRY, RSTRING_PTR(fname));
1002  found = search_required(path, &path, rb_feature_p);
1003  RUBY_DTRACE_HOOK(FIND_REQUIRE_RETURN, RSTRING_PTR(fname));
1004 
1005  if (found) {
1006  if (!path || !(ftptr = load_lock(RSTRING_PTR(path)))) {
1007  result = 0;
1008  }
1009  else if (!*ftptr) {
1010  result = TAG_RETURN;
1011  }
1012  else {
1013  switch (found) {
1014  case 'r':
1015  load_iseq_eval(ec, path);
1016  break;
1017 
1018  case 's':
1019  handle = (long)rb_vm_call_cfunc(rb_vm_top_self(), load_ext,
1021  rb_ary_push(ruby_dln_librefs, LONG2NUM(handle));
1022  break;
1023  }
1024  result = TAG_RETURN;
1025  }
1026  }
1027  }
1028  EC_POP_TAG();
1029  th = rb_ec_thread_ptr(ec);
1030  th->top_self = self;
1031  th->top_wrapper = wrapper;
1032  if (ftptr) load_unlock(RSTRING_PTR(path), !state);
1033 
1034  if (state) {
1035  if (state == TAG_FATAL) {
1036  EC_JUMP_TAG(ec, state);
1037  }
1038  else if (exception) {
1039  /* usually state == TAG_RAISE only, except for
1040  * rb_iseq_load_iseq in load_iseq_eval case */
1042  if (!NIL_P(exc)) ec->errinfo = exc;
1043  return TAG_RAISE;
1044  }
1045  else if (state == TAG_RETURN) {
1046  return TAG_RAISE;
1047  }
1048  RB_GC_GUARD(fname);
1049  /* never TAG_RETURN */
1050  return state;
1051  }
1052  if (!NIL_P(ec->errinfo)) {
1053  if (!exception) return TAG_RAISE;
1054  rb_exc_raise(ec->errinfo);
1055  }
1056 
1057  if (result == TAG_RETURN) rb_provide_feature(path);
1058  ec->errinfo = errinfo;
1059 
1060  RUBY_DTRACE_HOOK(REQUIRE_RETURN, RSTRING_PTR(fname));
1061 
1062  return result;
1063 }
1064 
1065 int
1067 {
1069  return require_internal(ec, fname, 1);
1070 }
1071 
1072 int
1073 ruby_require_internal(const char *fname, unsigned int len)
1074 {
1075  struct RString fake;
1076  VALUE str = rb_setup_fake_str(&fake, fname, len, 0);
1078  int result = require_internal(ec, str, 0);
1080  return result == TAG_RETURN ? 1 : result ? -1 : 0;
1081 }
1082 
1083 VALUE
1084 rb_require_safe(VALUE fname, int safe)
1085 {
1086  rb_warn("rb_require_safe will be removed in Ruby 3.0");
1088  int result = require_internal(ec, fname, 1);
1089 
1090  if (result > TAG_RETURN) {
1091  EC_JUMP_TAG(ec, result);
1092  }
1093  if (result < 0) {
1094  load_failed(fname);
1095  }
1096 
1097  return result ? Qtrue : Qfalse;
1098 }
1099 
1100 VALUE
1102 {
1104  int result = require_internal(ec, fname, 1);
1105 
1106  if (result > TAG_RETURN) {
1107  EC_JUMP_TAG(ec, result);
1108  }
1109  if (result < 0) {
1110  load_failed(fname);
1111  }
1112 
1113  return result ? Qtrue : Qfalse;
1114 }
1115 
1116 VALUE
1117 rb_require(const char *fname)
1118 {
1119  return rb_require_string(rb_str_new_cstr(fname));
1120 }
1121 
1122 static int
1123 register_init_ext(st_data_t *key, st_data_t *value, st_data_t init, int existing)
1124 {
1125  const char *name = (char *)*key;
1126  if (existing) {
1127  /* already registered */
1128  rb_warn("%s is already registered", name);
1129  }
1130  else {
1131  *value = (st_data_t)MEMO_NEW(0, 0, init);
1133  }
1134  return ST_CONTINUE;
1135 }
1136 
1137 RUBY_FUNC_EXPORTED void
1138 ruby_init_ext(const char *name, void (*init)(void))
1139 {
1140  st_table *loading_tbl = get_loading_table();
1141 
1142  if (rb_provided(name))
1143  return;
1144  st_update(loading_tbl, (st_data_t)name, register_init_ext, (st_data_t)init);
1145 }
1146 
1147 /*
1148  * call-seq:
1149  * mod.autoload(module, filename) -> nil
1150  *
1151  * Registers _filename_ to be loaded (using Kernel::require)
1152  * the first time that _module_ (which may be a String or
1153  * a symbol) is accessed in the namespace of _mod_.
1154  *
1155  * module A
1156  * end
1157  * A.autoload(:B, "b")
1158  * A::B.doit # autoloads "b"
1159  */
1160 
1161 static VALUE
1162 rb_mod_autoload(VALUE mod, VALUE sym, VALUE file)
1163 {
1164  ID id = rb_to_id(sym);
1165 
1166  FilePathValue(file);
1167  rb_autoload_str(mod, id, file);
1168  return Qnil;
1169 }
1170 
1171 /*
1172  * call-seq:
1173  * mod.autoload?(name, inherit=true) -> String or nil
1174  *
1175  * Returns _filename_ to be loaded if _name_ is registered as
1176  * +autoload+ in the namespace of _mod_ or one of its ancestors.
1177  *
1178  * module A
1179  * end
1180  * A.autoload(:B, "b")
1181  * A.autoload?(:B) #=> "b"
1182  *
1183  * If +inherit+ is false, the lookup only checks the autoloads in the receiver:
1184  *
1185  * class A
1186  * autoload :CONST, "const.rb"
1187  * end
1188  *
1189  * class B < A
1190  * end
1191  *
1192  * B.autoload?(:CONST) #=> "const.rb", found in A (ancestor)
1193  * B.autoload?(:CONST, false) #=> nil, not found in B itself
1194  *
1195  */
1196 
1197 static VALUE
1198 rb_mod_autoload_p(int argc, VALUE *argv, VALUE mod)
1199 {
1200  int recur = (rb_check_arity(argc, 1, 2) == 1) ? TRUE : RTEST(argv[1]);
1201  VALUE sym = argv[0];
1202 
1203  ID id = rb_check_id(&sym);
1204  if (!id) {
1205  return Qnil;
1206  }
1207  return rb_autoload_at_p(mod, id, recur);
1208 }
1209 
1210 /*
1211  * call-seq:
1212  * autoload(module, filename) -> nil
1213  *
1214  * Registers _filename_ to be loaded (using Kernel::require)
1215  * the first time that _module_ (which may be a String or
1216  * a symbol) is accessed.
1217  *
1218  * autoload(:MyModule, "/usr/local/lib/modules/my_module.rb")
1219  */
1220 
1221 static VALUE
1222 rb_f_autoload(VALUE obj, VALUE sym, VALUE file)
1223 {
1225  if (NIL_P(klass)) {
1226  rb_raise(rb_eTypeError, "Can not set autoload on singleton class");
1227  }
1228  return rb_mod_autoload(klass, sym, file);
1229 }
1230 
1231 /*
1232  * call-seq:
1233  * autoload?(name, inherit=true) -> String or nil
1234  *
1235  * Returns _filename_ to be loaded if _name_ is registered as
1236  * +autoload+.
1237  *
1238  * autoload(:B, "b")
1239  * autoload?(:B) #=> "b"
1240  */
1241 
1242 static VALUE
1243 rb_f_autoload_p(int argc, VALUE *argv, VALUE obj)
1244 {
1245  /* use rb_vm_cbase() as same as rb_f_autoload. */
1246  VALUE klass = rb_vm_cbase();
1247  if (NIL_P(klass)) {
1248  return Qnil;
1249  }
1250  return rb_mod_autoload_p(argc, argv, klass);
1251 }
1252 
1253 void
1255 {
1256 #undef rb_intern
1257 #define rb_intern(str) rb_intern2((str), strlen(str))
1258  rb_vm_t *vm = GET_VM();
1259  static const char var_load_path[] = "$:";
1260  ID id_load_path = rb_intern2(var_load_path, sizeof(var_load_path)-1);
1261 
1262  rb_define_hooked_variable(var_load_path, (VALUE*)vm, load_path_getter, rb_gvar_readonly_setter);
1263  rb_alias_variable(rb_intern("$-I"), id_load_path);
1264  rb_alias_variable(rb_intern("$LOAD_PATH"), id_load_path);
1265  vm->load_path = rb_ary_new();
1266  vm->expanded_load_path = rb_ary_tmp_new(0);
1267  vm->load_path_snapshot = rb_ary_tmp_new(0);
1268  vm->load_path_check_cache = 0;
1269  rb_define_singleton_method(vm->load_path, "resolve_feature_path", rb_resolve_feature_path, 1);
1270 
1271  rb_define_virtual_variable("$\"", get_LOADED_FEATURES, 0);
1272  rb_define_virtual_variable("$LOADED_FEATURES", get_LOADED_FEATURES, 0);
1273  vm->loaded_features = rb_ary_new();
1274  vm->loaded_features_snapshot = rb_ary_tmp_new(0);
1275  vm->loaded_features_index = st_init_numtable();
1276 
1277  rb_define_global_function("load", rb_f_load, -1);
1278  rb_define_global_function("require", rb_f_require, 1);
1279  rb_define_global_function("require_relative", rb_f_require_relative, 1);
1280  rb_define_method(rb_cModule, "autoload", rb_mod_autoload, 2);
1281  rb_define_method(rb_cModule, "autoload?", rb_mod_autoload_p, -1);
1282  rb_define_global_function("autoload", rb_f_autoload, 2);
1283  rb_define_global_function("autoload?", rb_f_autoload_p, -1);
1284 
1285  ruby_dln_librefs = rb_ary_tmp_new(0);
1286  rb_gc_register_mark_object(ruby_dln_librefs);
1287 }
expand_type
expand_type
Definition: load.c:31
rb_feature_provided
int rb_feature_provided(const char *feature, const char **loading)
Definition: load.c:519
rb_parser_new
VALUE rb_parser_new(void)
Definition: ripper.c:19221
IS_DLEXT
#define IS_DLEXT(e)
Definition: load.c:20
i
uint32_t i
Definition: rb_mjit_min_header-2.7.1.h:5425
ID
unsigned long ID
Definition: ruby.h:103
rb_vm_struct::loaded_features_index
struct st_table * loaded_features_index
Definition: vm_core.h:621
obj
const VALUE VALUE obj
Definition: rb_mjit_min_header-2.7.1.h:5703
rb_fstring
VALUE rb_fstring(VALUE)
Definition: string.c:312
Check_Type
#define Check_Type(v, t)
Definition: ruby.h:595
TRUE
#define TRUE
Definition: nkf.h:175
long
#define long
Definition: rb_mjit_min_header-2.7.1.h:2848
rb_str_freeze
VALUE rb_str_freeze(VALUE)
Definition: string.c:2616
rb_vm_jump_tag_but_local_jump
void rb_vm_jump_tag_but_local_jump(int state)
Definition: vm.c:1510
rb_iseq_eval
VALUE rb_iseq_eval(const rb_iseq_t *iseq)
Definition: vm.c:2163
rb_check_id
ID rb_check_id(volatile VALUE *)
Returns ID for the given name if it is interned already, or 0.
Definition: symbol.c:919
xcalloc
#define xcalloc
Definition: defines.h:213
rb_file_expand_path_fast
VALUE rb_file_expand_path_fast(VALUE fname, VALUE dname)
Definition: file.c:4025
rb_dir_getwd_ospath
VALUE rb_dir_getwd_ospath(void)
Definition: dir.c:1117
rb_str_new2
#define rb_str_new2
Definition: intern.h:903
rb_thread_struct::top_self
VALUE top_self
Definition: vm_core.h:923
klass
VALUE klass
Definition: rb_mjit_min_header-2.7.1.h:13179
rb_ast_struct::body
rb_ast_body_t body
Definition: node.h:402
st_data_t
unsigned long st_data_t
Definition: rb_mjit_min_header-2.7.1.h:5324
rb_f_require_relative
VALUE rb_f_require_relative(VALUE obj, VALUE fname)
Definition: load.c:823
rb_f_require
VALUE rb_f_require(VALUE obj, VALUE fname)
Definition: load.c:809
rb_iseq_struct
Definition: vm_core.h:456
IS_SOEXT
#define IS_SOEXT(e)
Definition: load.c:16
rb_gc_register_mark_object
void rb_gc_register_mark_object(VALUE obj)
Definition: gc.c:7065
EXPAND_HOME
@ EXPAND_HOME
Definition: load.c:34
rb_warn
void rb_warn(const char *fmt,...)
Definition: error.c:313
rb_backtrace_each
void rb_backtrace_each(VALUE(*iter)(VALUE recv, VALUE str), VALUE output)
Definition: vm_backtrace.c:855
imemo_memo
@ imemo_memo
Definition: internal.h:1138
rb_ary_shared_with_p
VALUE rb_ary_shared_with_p(VALUE ary1, VALUE ary2)
Definition: array.c:661
rb_warning
void rb_warning(const char *fmt,...)
Definition: error.c:334
EXPAND_RELATIVE
@ EXPAND_RELATIVE
Definition: load.c:33
rb_ary_free
void rb_ary_free(VALUE ary)
Definition: array.c:786
ST_STOP
@ ST_STOP
Definition: st.h:99
rb_ast_dispose
void rb_ast_dispose(rb_ast_t *ast)
Definition: node.c:1389
INT2FIX
#define INT2FIX(i)
Definition: ruby.h:263
n
const char size_t n
Definition: rb_mjit_min_header-2.7.1.h:5417
strchr
char * strchr(char *, char)
st_hash
st_index_t st_hash(const void *ptr, size_t len, st_index_t h)
Definition: st.c:1897
RSTRING_PTR
#define RSTRING_PTR(str)
Definition: ruby.h:1009
rb_thread_struct::top_wrapper
VALUE top_wrapper
Definition: vm_core.h:924
rb_str_new_cstr
#define rb_str_new_cstr(str)
Definition: rb_mjit_min_header-2.7.1.h:6078
rb_iseq_new_top
rb_iseq_t * rb_iseq_new_top(const rb_ast_body_t *ast, VALUE name, VALUE path, VALUE realpath, const rb_iseq_t *parent)
Definition: iseq.c:769
st_init_numtable
st_table * st_init_numtable(void)
Definition: st.c:653
loaded_feature_searching::load_path
VALUE load_path
Definition: load.c:351
rb_gvar_readonly_setter
void rb_gvar_readonly_setter(VALUE v, ID id, VALUE *_)
Definition: variable.c:412
rb_get_expanded_load_path
VALUE rb_get_expanded_load_path(void)
Definition: load.c:92
VALUE
unsigned long VALUE
Definition: ruby.h:102
rb_scope_visibility_set
void rb_scope_visibility_set(rb_method_visibility_t)
Definition: vm_method.c:1138
GET_VM
#define GET_VM()
Definition: vm_core.h:1764
rb_module_new
VALUE rb_module_new(void)
Definition: class.c:758
encoding.h
rb_ary_replace
VALUE rb_ary_replace(VALUE copy, VALUE orig)
Definition: array.c:3811
ruby_verbose
#define ruby_verbose
Definition: ruby.h:1925
rb_ary_store
void rb_ary_store(VALUE ary, long idx, VALUE val)
Definition: array.c:1079
RB_TYPE_P
#define RB_TYPE_P(obj, type)
Definition: ruby.h:560
TAG_FATAL
#define TAG_FATAL
Definition: vm_core.h:205
rb_cModule
RUBY_EXTERN VALUE rb_cModule
Definition: ruby.h:2034
DLEXT
#define DLEXT
Definition: rb_mjit_min_header-2.7.1.h:429
rb_define_global_function
void rb_define_global_function(const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a global function.
Definition: class.c:1787
EC_JUMP_TAG
#define EC_JUMP_TAG(ec, st)
Definition: eval_intern.h:184
rb_vm_struct::loaded_features
VALUE loaded_features
Definition: vm_core.h:619
rb_load_protect
void rb_load_protect(VALUE fname, int wrap, int *pstate)
Definition: load.c:657
arg
VALUE arg
Definition: rb_mjit_min_header-2.7.1.h:5562
rb_str_cat2
#define rb_str_cat2
Definition: intern.h:912
iseq
const rb_iseq_t * iseq
Definition: rb_mjit_min_header-2.7.1.h:13426
Qundef
#define Qundef
Definition: ruby.h:470
rb_define_singleton_method
void rb_define_singleton_method(VALUE obj, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a singleton method for obj.
Definition: class.c:1755
loaded_feature_searching::type
int type
Definition: load.c:350
rb_define_method
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1551
GET_EC
#define GET_EC()
Definition: vm_core.h:1766
feature_func
int(* feature_func)(const char *feature, const char *ext, int rb, int expanded, const char **fn)
Definition: load.c:833
rb_loaderror
void rb_loaderror(const char *fmt,...)
Definition: error.c:2688
Qfalse
#define Qfalse
Definition: ruby.h:467
rb_get_path
VALUE rb_get_path(VALUE obj)
Definition: file.c:230
FilePathValue
#define FilePathValue(v)
Definition: ruby.h:624
rb_vm_struct::expanded_load_path
VALUE expanded_load_path
Definition: vm_core.h:618
loaded_feature_searching::result
const char * result
Definition: load.c:352
SPECIAL_CONST_P
#define SPECIAL_CONST_P(x)
Definition: ruby.h:1313
Init_load
void Init_load(void)
Definition: load.c:1254
rb_parser_load_file
RUBY_SYMBOL_EXPORT_END void * rb_parser_load_file(VALUE parser, VALUE name)
Definition: ruby.c:2193
NULL
#define NULL
Definition: _sdbm.c:101
rb_filesystem_str_new_cstr
VALUE rb_filesystem_str_new_cstr(const char *)
Definition: string.c:1117
rb_check_realpath
VALUE rb_check_realpath(VALUE basedir, VALUE path, rb_encoding *enc)
Definition: file.c:4417
ST_DELETE
@ ST_DELETE
Definition: st.h:99
IS_RBEXT
#define IS_RBEXT(e)
Definition: load.c:15
PRIsVALUE
#define PRIsVALUE
Definition: ruby.h:166
rb_vm_cbase
VALUE rb_vm_cbase(void)
Definition: vm.c:1425
EXPAND_NON_CACHE
@ EXPAND_NON_CACHE
Definition: load.c:35
st_insert
int st_insert(st_table *tab, st_data_t key, st_data_t value)
Definition: st.c:1171
FIX2LONG
#define FIX2LONG(x)
Definition: ruby.h:394
ID2SYM
#define ID2SYM(x)
Definition: ruby.h:414
strlen
size_t strlen(const char *)
OBJ_FREEZE
#define OBJ_FREEZE(x)
Definition: ruby.h:1377
rb_intern
#define rb_intern(str)
rb_autoload_at_p
VALUE rb_autoload_at_p(VALUE, ID, int)
Definition: variable.c:2287
MEMO
MEMO.
Definition: internal.h:1278
rb_check_arity
#define rb_check_arity
Definition: intern.h:347
RUBY_FUNC_EXPORTED
#define RUBY_FUNC_EXPORTED
Definition: defines.h:391
rb_vm_struct::load_path
VALUE load_path
Definition: vm_core.h:615
VM_BLOCK_HANDLER_NONE
#define VM_BLOCK_HANDLER_NONE
Definition: vm_core.h:1291
rb_str_resize
VALUE rb_str_resize(VALUE, long)
Definition: string.c:2709
exc
const rb_iseq_t const VALUE exc
Definition: rb_mjit_min_header-2.7.1.h:13426
rb_raise
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:2669
MEMO::u3
union MEMO::@109 u3
rb_ary_entry
VALUE rb_ary_entry(VALUE ary, long offset)
Definition: array.c:1512
LONG2NUM
#define LONG2NUM(x)
Definition: ruby.h:1644
void
void
Definition: rb_mjit_min_header-2.7.1.h:13198
probes.h
rb_alias_variable
void rb_alias_variable(ID, ID)
Definition: variable.c:756
DLEXT_MAXLEN
#define DLEXT_MAXLEN
Definition: defines.h:456
rb_load_fail
void rb_load_fail(VALUE path, const char *err)
Definition: error.c:2965
rb_ast_struct
Definition: node.h:399
rb_thread_shield_new
VALUE rb_thread_shield_new(void)
Definition: thread.c:4790
rb_thread_shield_wait
VALUE rb_thread_shield_wait(VALUE self)
Definition: thread.c:4806
EC_POP_TAG
#define EC_POP_TAG()
Definition: eval_intern.h:137
rb_require_string
VALUE rb_require_string(VALUE fname)
Definition: load.c:1101
rb_setup_fake_str
VALUE rb_setup_fake_str(struct RString *fake_str, const char *name, long len, rb_encoding *enc)
Definition: string.c:385
iseq.h
rb_iseq_load_iseq
const rb_iseq_t * rb_iseq_load_iseq(VALUE fname)
Definition: iseq.c:847
T_FIXNUM
#define T_FIXNUM
Definition: ruby.h:535
rb_ary_cat
VALUE rb_ary_cat(VALUE ary, const VALUE *argv, long len)
Definition: array.c:1208
rb_ary_new_from_args
#define rb_ary_new_from_args(n,...)
Definition: rb_mjit_min_header-2.7.1.h:7161
rb_ary_tmp_new
VALUE rb_ary_tmp_new(long capa)
Definition: array.c:768
rb_file_absolute_path
VALUE rb_file_absolute_path(VALUE fname, VALUE dname)
Definition: file.c:4072
rb_vm_top_self
VALUE rb_vm_top_self(void)
Definition: vm.c:3347
sym
#define sym(x)
Definition: date_core.c:3716
st_data_t
RUBY_SYMBOL_EXPORT_BEGIN typedef unsigned long st_data_t
Definition: st.h:22
rb_to_id
ID rb_to_id(VALUE)
Definition: string.c:11146
rb_realpath_internal
VALUE rb_realpath_internal(VALUE basedir, VALUE path, int strict)
Definition: file.c:4409
rb_execution_context_struct::errinfo
VALUE errinfo
Definition: vm_core.h:875
rb_file_load_ok
int rb_file_load_ok(const char *path)
Definition: file.c:6222
rb_str_equal
VALUE rb_str_equal(VALUE str1, VALUE str2)
Definition: string.c:3267
rb_ary_push
VALUE rb_ary_push(VALUE ary, VALUE item)
Definition: array.c:1195
rb_vm_struct::load_path_check_cache
VALUE load_path_check_cache
Definition: vm_core.h:617
EC_EXEC_TAG
#define EC_EXEC_TAG()
Definition: eval_intern.h:181
rb_obj_freeze
VALUE rb_obj_freeze(VALUE)
Make the object unmodifiable.
Definition: object.c:1080
EXPAND_ALL
@ EXPAND_ALL
Definition: load.c:32
rb_provided
int rb_provided(const char *feature)
Definition: load.c:513
rb_require_internal
int rb_require_internal(VALUE fname)
Definition: load.c:1066
ruby_init_ext
RUBY_FUNC_EXPORTED void ruby_init_ext(const char *name, void(*init)(void))
Definition: load.c:1138
rb_file_dirname
VALUE rb_file_dirname(VALUE fname)
Definition: file.c:4645
rb_eTypeError
VALUE rb_eTypeError
Definition: error.c:922
rb_require
VALUE rb_require(const char *fname)
Definition: load.c:1117
rb_eRuntimeError
VALUE rb_eRuntimeError
Definition: error.c:920
MEMO_NEW
#define MEMO_NEW(a, b, c)
Definition: internal.h:1296
mod
#define mod(x, y)
Definition: date_strftime.c:28
rb_get_path_check_convert
VALUE rb_get_path_check_convert(VALUE obj)
Definition: file.c:211
RARRAY_AREF
#define RARRAY_AREF(a, i)
Definition: ruby.h:1101
StringValuePtr
#define StringValuePtr(v)
Definition: ruby.h:603
strlcpy
RUBY_EXTERN size_t strlcpy(char *, const char *, size_t)
Definition: strlcpy.c:29
FALSE
#define FALSE
Definition: nkf.h:174
RString
Definition: ruby.h:988
METHOD_VISI_PUBLIC
@ METHOD_VISI_PUBLIC
Definition: method.h:28
rb_thread_shield_destroy
VALUE rb_thread_shield_destroy(VALUE self)
Definition: thread.c:4846
RArray
Definition: ruby.h:1048
st_update
int st_update(st_table *tab, st_data_t key, st_update_callback_func *func, st_data_t arg)
Definition: st.c:1510
rb_extend_object
void rb_extend_object(VALUE obj, VALUE module)
Extend the object with the module.
Definition: eval.c:1701
index
int index
Definition: rb_mjit_min_header-2.7.1.h:11171
key
key
Definition: openssl_missing.h:181
path
VALUE path
Definition: rb_mjit_min_header-2.7.1.h:7300
loaded_feature_searching
Definition: load.c:347
rb_vm_make_jump_tag_but_local_jump
VALUE rb_vm_make_jump_tag_but_local_jump(int state, VALUE val)
Definition: vm.c:1478
TAG_RAISE
#define TAG_RAISE
Definition: vm_core.h:203
RARRAY_LEN
#define RARRAY_LEN(a)
Definition: ruby.h:1070
st_foreach
int st_foreach(st_table *tab, st_foreach_callback_func *func, st_data_t arg)
Definition: st.c:1718
rb_scan_args
#define rb_scan_args(argc, argvp, fmt,...)
Definition: rb_mjit_min_header-2.7.1.h:6333
rb_current_realfilepath
VALUE rb_current_realfilepath(void)
Definition: vm_eval.c:2462
buf
unsigned char buf[MIME_BUF_SIZE]
Definition: nkf.c:4322
MEMO_CAST
#define MEMO_CAST(m)
Definition: internal.h:1294
rb_exc_raise
void rb_exc_raise(VALUE mesg)
Raises an exception in the current thread.
Definition: eval.c:668
rb_intern2
ID rb_intern2(const char *, long)
Definition: symbol.c:653
rb_str_append
VALUE rb_str_append(VALUE, VALUE)
Definition: string.c:2965
rb_require_safe
VALUE rb_require_safe(VALUE fname, int safe)
Definition: load.c:1084
StringValue
use StringValue() instead")))
internal.h
T_ARRAY
#define T_ARRAY
Definition: ruby.h:530
argv
char ** argv
Definition: ruby.c:223
f
#define f
rb_set_errinfo
void rb_set_errinfo(VALUE err)
Sets the current exception ($!) to the given value.
Definition: eval.c:1896
rb_vm_struct::load_path_snapshot
VALUE load_path_snapshot
Definition: vm_core.h:616
ST_CONTINUE
@ ST_CONTINUE
Definition: st.h:99
rb_vm_struct::loaded_features_snapshot
VALUE loaded_features_snapshot
Definition: vm_core.h:620
rb_str_subseq
VALUE rb_str_subseq(VALUE, long, long)
Definition: string.c:2474
rb_get_path_check_to_string
VALUE rb_get_path_check_to_string(VALUE obj)
Definition: file.c:196
strrchr
char * strrchr(const char *, const char)
str
char str[HTML_ESCAPE_MAX_LEN+1]
Definition: escape.c:18
loaded_feature_searching::len
long len
Definition: load.c:349
MEMCPY
#define MEMCPY(p1, p2, type, n)
Definition: ruby.h:1753
rb_parser_set_context
VALUE rb_parser_set_context(VALUE vparser, const struct rb_iseq_struct *base, int main)
Definition: ripper.c:19231
int
__inline__ int
Definition: rb_mjit_min_header-2.7.1.h:2807
dln_load
void * dln_load(const char *file)
Definition: dln.c:1261
rb_autoload_str
void rb_autoload_str(VALUE mod, ID id, VALUE file)
Definition: variable.c:1933
rb_fstring_cstr
#define rb_fstring_cstr(str)
Definition: rb_mjit_min_header-2.7.1.h:7645
rb_str_encode_ospath
VALUE rb_str_encode_ospath(VALUE path)
Definition: file.c:236
NIL_P
#define NIL_P(v)
Definition: ruby.h:482
TAG_NONE
#define TAG_NONE
Definition: vm_core.h:197
rb_warning_string
VALUE rb_warning_string(const char *fmt,...)
Definition: error.c:344
argc
int argc
Definition: ruby.c:222
recur
#define recur(fmt)
Definition: date_strptime.c:152
NORETURN
NORETURN(static void load_failed(VALUE))
rb_vm_call_cfunc
VALUE rb_vm_call_cfunc(VALUE recv, VALUE(*func)(VALUE), VALUE arg, VALUE block_handler, VALUE filename)
Definition: vm.c:2212
rb_vm_struct
Definition: vm_core.h:576
xfree
#define xfree
Definition: defines.h:216
rb_thread_shield_release
VALUE rb_thread_shield_release(VALUE self)
Definition: thread.c:4835
RUBY_DTRACE_HOOK
#define RUBY_DTRACE_HOOK(name, arg)
Definition: internal.h:2591
MEMO::value
const VALUE value
Definition: internal.h:1286
v
int VALUE v
Definition: rb_mjit_min_header-2.7.1.h:12257
RBASIC
#define RBASIC(obj)
Definition: ruby.h:1267
ruby_strdup
char * ruby_strdup(const char *)
Definition: util.c:527
ruby_sized_xfree
#define ruby_sized_xfree(ptr, size)
Definition: rb_mjit_min_header-2.7.1.h:7319
_
#define _(args)
Definition: dln.h:28
EC_PUSH_TAG
#define EC_PUSH_TAG(ec)
Definition: eval_intern.h:130
Qtrue
#define Qtrue
Definition: ruby.h:468
OBJ_FROZEN
#define OBJ_FROZEN(x)
Definition: ruby.h:1375
len
uint8_t len
Definition: escape.c:17
T_STRING
#define T_STRING
Definition: ruby.h:528
strncmp
int strncmp(const char *, const char *, size_t)
ruby::backward::cxxanyargs::rb_define_hooked_variable
void rb_define_hooked_variable(const char *q, VALUE *w, type *e, void_type *r)
Define a function-backended global variable.
Definition: cxxanyargs.hpp:106
rb_is_absolute_path
int rb_is_absolute_path(const char *path)
Definition: file.c:6089
eval_intern.h
rb_provide
void rb_provide(const char *feature)
Definition: load.c:563
ruby_require_internal
int ruby_require_internal(const char *fname, unsigned int len)
Definition: load.c:1073
rb_resolve_feature_path
VALUE rb_resolve_feature_path(VALUE klass, VALUE fname)
Definition: load.c:947
rb_find_file
VALUE rb_find_file(VALUE path)
Definition: file.c:6336
rb_ary_new
VALUE rb_ary_new(void)
Definition: array.c:723
rb_load
void rb_load(VALUE fname, int wrap)
Definition: load.c:649
ruby::backward::cxxanyargs::rb_define_virtual_variable
void rb_define_virtual_variable(const char *q, type *w, void_type *e)
Define a function-backended global variable.
Definition: cxxanyargs.hpp:59
Qnil
#define Qnil
Definition: ruby.h:469
rb_fstring_lit
#define rb_fstring_lit(str)
Definition: internal.h:2128
st_lookup
int st_lookup(st_table *tab, st_data_t key, st_data_t *value)
Definition: st.c:1101
util.h
rb_find_file_ext
int rb_find_file_ext(VALUE *filep, const char *const *ext)
Definition: file.c:6270
RB_GC_GUARD
#define RB_GC_GUARD(v)
Definition: ruby.h:585
numberof
#define numberof(array)
Definition: etc.c:618
rb_thread_struct
Definition: vm_core.h:910
rb_str_tmp_new
VALUE rb_str_tmp_new(long)
Definition: string.c:1343
MEMO::state
long state
Definition: internal.h:1285
RSTRING_LEN
#define RSTRING_LEN(str)
Definition: ruby.h:1005
st_table
Definition: st.h:79
MEMO::func
void(* func)(void)
Definition: internal.h:1287
ruby_tag_type
ruby_tag_type
Definition: vm_core.h:184
loaded_feature_searching::name
const char * name
Definition: load.c:348
RTEST
#define RTEST(v)
Definition: ruby.h:481
ruby::backward::cxxanyargs::type
VALUE type(ANYARGS)
ANYARGS-ed function type.
Definition: cxxanyargs.hpp:39
TAG_RETURN
#define TAG_RETURN
Definition: vm_core.h:198
rb_obj_clone
VALUE rb_obj_clone(VALUE)
Almost same as Object::clone.
Definition: object.c:410
st_get_key
int st_get_key(st_table *tab, st_data_t key, st_data_t *result)
Definition: st.c:1130
rb_class_real
VALUE rb_class_real(VALUE cl)
Looks up the nearest ancestor of cl, skipping singleton classes or module inclusions.
Definition: object.c:202
dln.h
name
const char * name
Definition: nkf.c:208
rb_execution_context_struct
Definition: vm_core.h:843