Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 707 lines (631 sloc) 16.911 kb
511dc44 initial import
Laurent Sansonetti authored
1 /*
2 * load methods from eval.c
3 */
4
5 #include "eval_intern.h"
6
7 VALUE ruby_dln_librefs;
8
9 #define IS_RBEXT(e) (strcmp(e, ".rb") == 0)
10 #define IS_SOEXT(e) (strcmp(e, ".so") == 0 || strcmp(e, ".o") == 0)
11 #ifdef DLEXT2
12 #define IS_DLEXT(e) (strcmp(e, DLEXT) == 0 || strcmp(e, DLEXT2) == 0)
13 #else
14 #define IS_DLEXT(e) (strcmp(e, DLEXT) == 0)
15 #endif
16
17
18 static const char *const loadable_ext[] = {
19 ".rb", DLEXT,
20 #ifdef DLEXT2
21 DLEXT2,
22 #endif
23 0
24 };
25
eee9d7b sync with ruby trunk r15665
Laurent Sansonetti authored
26 VALUE
27 rb_get_load_path(void)
511dc44 initial import
Laurent Sansonetti authored
28 {
eee9d7b sync with ruby trunk r15665
Laurent Sansonetti authored
29 VALUE load_path = GET_VM()->load_path;
511dc44 initial import
Laurent Sansonetti authored
30 VALUE ary = rb_ary_new2(RARRAY_LEN(load_path));
31 long i;
32
33 for (i = 0; i < RARRAY_LEN(load_path); ++i) {
f0849e8 - Hash is now a shortcut to NSMutableDictionary.
Laurent Sansonetti authored
34 rb_ary_push(ary, rb_file_expand_path(RARRAY_AT(load_path, i), Qnil));
511dc44 initial import
Laurent Sansonetti authored
35 }
36 return ary;
37 }
38
39 static VALUE
eee9d7b sync with ruby trunk r15665
Laurent Sansonetti authored
40 load_path_getter(ID id, rb_vm_t *vm)
41 {
42 return vm->load_path;
43 }
44
45 static VALUE
511dc44 initial import
Laurent Sansonetti authored
46 get_loaded_features(void)
47 {
48 return GET_VM()->loaded_features;
49 }
50
51 static st_table *
52 get_loading_table(void)
53 {
54 return GET_VM()->loading_table;
55 }
56
57 static VALUE
58 loaded_feature_path(const char *name, long vlen, const char *feature, long len,
59 int type, VALUE load_path)
60 {
61 long i;
62
63 for (i = 0; i < RARRAY_LEN(load_path); ++i) {
f0849e8 - Hash is now a shortcut to NSMutableDictionary.
Laurent Sansonetti authored
64 VALUE p = RARRAY_AT(load_path, i);
511dc44 initial import
Laurent Sansonetti authored
65 const char *s = StringValuePtr(p);
70fef6e RSTRING_PTR/RSTRING_LEN -> RSTRING_BYTEPTR/RSTRING_BYTELEN, RSTRING_C…
Laurent Sansonetti authored
66 long n = RSTRING_LEN(p);
511dc44 initial import
Laurent Sansonetti authored
67
68 if (vlen < n + len + 1) continue;
69 if (n && (strncmp(name, s, n) || name[n] != '/')) continue;
70 if (strncmp(name + n + 1, feature, len)) continue;
71 if (name[n+len+1] && name[n+len+1] != '.') continue;
72 switch (type) {
73 case 's':
74 if (IS_DLEXT(&name[n+len+1])) return p;
75 break;
76 case 'r':
77 if (IS_RBEXT(&name[n+len+1])) return p;
78 break;
79 default:
80 return p;
81 }
82 }
83 return 0;
84 }
85
86 struct loaded_feature_searching {
87 const char *name;
88 long len;
89 int type;
90 VALUE load_path;
91 const char *result;
92 };
93
94 static int
95 loaded_feature_path_i(st_data_t v, st_data_t b, st_data_t f)
96 {
97 const char *s = (const char *)v;
98 struct loaded_feature_searching *fp = (struct loaded_feature_searching *)f;
99 VALUE p = loaded_feature_path(s, strlen(s), fp->name, fp->len,
100 fp->type, fp->load_path);
101 if (!p) return ST_CONTINUE;
102 fp->result = s;
103 return ST_STOP;
104 }
105
106 static int
107 rb_feature_p(const char *feature, const char *ext, int rb, int expanded, const char **fn)
108 {
109 VALUE v, features, p, load_path = 0;
110 const char *f, *e;
17d530a fixing some regressions
Laurent Sansonetti authored
111 long i, count, len, elen, n;
511dc44 initial import
Laurent Sansonetti authored
112 st_table *loading_tbl;
113 st_data_t data;
114 int type;
115
116 if (fn) *fn = 0;
117 if (ext) {
118 len = ext - feature;
119 elen = strlen(ext);
120 type = rb ? 'r' : 's';
121 }
122 else {
123 len = strlen(feature);
124 elen = 0;
125 type = 0;
126 }
127 features = get_loaded_features();
17d530a fixing some regressions
Laurent Sansonetti authored
128 for (i = 0, count = RARRAY_LEN(features); i < count; ++i) {
f0849e8 - Hash is now a shortcut to NSMutableDictionary.
Laurent Sansonetti authored
129 v = RARRAY_AT(features, i);
17d530a fixing some regressions
Laurent Sansonetti authored
130 f = StringValueCStr(v);
70fef6e RSTRING_PTR/RSTRING_LEN -> RSTRING_BYTEPTR/RSTRING_BYTELEN, RSTRING_C…
Laurent Sansonetti authored
131 if ((n = RSTRING_LEN(v)) < len) continue;
511dc44 initial import
Laurent Sansonetti authored
132 if (strncmp(f, feature, len) != 0) {
133 if (expanded) continue;
eee9d7b sync with ruby trunk r15665
Laurent Sansonetti authored
134 if (!load_path) load_path = rb_get_load_path();
511dc44 initial import
Laurent Sansonetti authored
135 if (!(p = loaded_feature_path(f, n, feature, len, type, load_path)))
136 continue;
70fef6e RSTRING_PTR/RSTRING_LEN -> RSTRING_BYTEPTR/RSTRING_BYTELEN, RSTRING_C…
Laurent Sansonetti authored
137 f += RSTRING_LEN(p) + 1;
511dc44 initial import
Laurent Sansonetti authored
138 }
139 if (!*(e = f + len)) {
140 if (ext) continue;
141 return 'u';
142 }
143 if (*e != '.') continue;
144 if ((!rb || !ext) && (IS_SOEXT(e) || IS_DLEXT(e))) {
145 return 's';
146 }
147 if ((rb || !ext) && (IS_RBEXT(e))) {
148 return 'r';
149 }
150 }
151 loading_tbl = get_loading_table();
152 if (loading_tbl) {
153 f = 0;
154 if (!expanded) {
155 struct loaded_feature_searching fs;
156 fs.name = feature;
157 fs.len = len;
158 fs.type = type;
eee9d7b sync with ruby trunk r15665
Laurent Sansonetti authored
159 fs.load_path = load_path ? load_path : rb_get_load_path();
511dc44 initial import
Laurent Sansonetti authored
160 fs.result = 0;
161 st_foreach(loading_tbl, loaded_feature_path_i, (st_data_t)&fs);
162 if ((f = fs.result) != 0) {
163 if (fn) *fn = f;
164 goto loading;
165 }
166 }
167 if (st_get_key(loading_tbl, (st_data_t)feature, &data)) {
168 if (fn) *fn = (const char*)data;
169 loading:
170 if (!ext) return 'u';
171 return !IS_RBEXT(ext) ? 's' : 'r';
172 }
173 else {
174 VALUE bufstr;
175 char *buf;
176
177 if (ext && *ext) return 0;
178 bufstr = rb_str_tmp_new(len + DLEXT_MAXLEN);
70fef6e RSTRING_PTR/RSTRING_LEN -> RSTRING_BYTEPTR/RSTRING_BYTELEN, RSTRING_C…
Laurent Sansonetti authored
179 buf = RSTRING_BYTEPTR(bufstr); /* ok */
511dc44 initial import
Laurent Sansonetti authored
180 MEMCPY(buf, feature, char, len);
181 for (i = 0; (e = loadable_ext[i]) != 0; i++) {
182 strncpy(buf + len, e, DLEXT_MAXLEN + 1);
183 if (st_get_key(loading_tbl, (st_data_t)buf, &data)) {
184 rb_str_resize(bufstr, 0);
185 if (fn) *fn = (const char*)data;
186 return i ? 's' : 'r';
187 }
188 }
189 rb_str_resize(bufstr, 0);
190 }
191 }
192 return 0;
193 }
194
195 int
196 rb_provided(const char *feature)
197 {
198 const char *ext = strrchr(feature, '.');
eee9d7b sync with ruby trunk r15665
Laurent Sansonetti authored
199 volatile VALUE fullpath = 0;
511dc44 initial import
Laurent Sansonetti authored
200
eee9d7b sync with ruby trunk r15665
Laurent Sansonetti authored
201 if (*feature == '.' &&
202 (feature[1] == '/' || strncmp(feature+1, "./", 2) == 0)) {
203 fullpath = rb_file_expand_path(rb_str_new2(feature), Qnil);
70fef6e RSTRING_PTR/RSTRING_LEN -> RSTRING_BYTEPTR/RSTRING_BYTELEN, RSTRING_C…
Laurent Sansonetti authored
204 feature = RSTRING_PTR(fullpath);
eee9d7b sync with ruby trunk r15665
Laurent Sansonetti authored
205 }
511dc44 initial import
Laurent Sansonetti authored
206 if (ext && !strchr(ext, '/')) {
207 if (IS_RBEXT(ext)) {
208 if (rb_feature_p(feature, ext, Qtrue, Qfalse, 0)) return Qtrue;
209 return Qfalse;
210 }
211 else if (IS_SOEXT(ext) || IS_DLEXT(ext)) {
212 if (rb_feature_p(feature, ext, Qfalse, Qfalse, 0)) return Qtrue;
213 return Qfalse;
214 }
215 }
216 if (rb_feature_p(feature, feature + strlen(feature), Qtrue, Qfalse, 0))
217 return Qtrue;
218 return Qfalse;
219 }
220
221 static void
222 rb_provide_feature(VALUE feature)
223 {
224 rb_ary_push(get_loaded_features(), feature);
225 }
226
227 void
228 rb_provide(const char *feature)
229 {
230 rb_provide_feature(rb_str_new2(feature));
231 }
232
233 NORETURN(static void load_failed(VALUE));
234
235 void
236 rb_load(VALUE fname, int wrap)
237 {
238 VALUE tmp;
239 int state;
240 rb_thread_t *th = GET_THREAD();
241 volatile VALUE wrapper = th->top_wrapper;
242 volatile VALUE self = th->top_self;
243 volatile int parse_in_eval;
244 volatile int loaded = Qfalse;
245 #ifndef __GNUC__
246 rb_thread_t *volatile th0 = th;
247 #endif
248
249 FilePathValue(fname);
250 fname = rb_str_new4(fname);
251 tmp = rb_find_file(fname);
252 if (!tmp) {
253 load_failed(fname);
254 }
255 RB_GC_GUARD(fname) = rb_str_new4(tmp);
256
257 th->errinfo = Qnil; /* ensure */
258
259 if (!wrap) {
260 rb_secure(4); /* should alter global state */
261 th->top_wrapper = 0;
262 }
263 else {
264 /* load in anonymous module as toplevel */
265 th->top_self = rb_obj_clone(rb_vm_top_self());
266 th->top_wrapper = rb_module_new();
267 rb_extend_object(th->top_self, th->top_wrapper);
268 }
269
270 parse_in_eval = th->parse_in_eval;
271 PUSH_TAG();
272 state = EXEC_TAG();
273 if (state == 0) {
274 NODE *node;
275 VALUE iseq;
276
277 th->parse_in_eval++;
70fef6e RSTRING_PTR/RSTRING_LEN -> RSTRING_BYTEPTR/RSTRING_BYTELEN, RSTRING_C…
Laurent Sansonetti authored
278 node = (NODE *)rb_load_file(RSTRING_PTR(fname));
511dc44 initial import
Laurent Sansonetti authored
279 th->parse_in_eval--;
280 loaded = Qtrue;
281 iseq = rb_iseq_new(node, rb_str_new2("<top (required)>"),
282 fname, Qfalse, ISEQ_TYPE_TOP);
283 rb_iseq_eval(iseq);
284 }
285 POP_TAG();
286
287 #ifndef __GNUC__
288 th = th0;
289 fname = RB_GC_GUARD(fname);
290 #endif
291 th->parse_in_eval = parse_in_eval;
292 th->top_self = self;
293 th->top_wrapper = wrapper;
294
295 if (!loaded) {
296 rb_exc_raise(GET_THREAD()->errinfo);
297 }
298 if (state) {
299 vm_jump_tag_but_local_jump(state, Qundef);
300 }
301
302 if (!NIL_P(GET_THREAD()->errinfo)) {
303 /* exception during load */
304 rb_exc_raise(th->errinfo);
305 }
306 }
307
308 void
309 rb_load_protect(VALUE fname, int wrap, int *state)
310 {
311 int status;
312
313 PUSH_TAG();
314 if ((status = EXEC_TAG()) == 0) {
315 rb_load(fname, wrap);
316 }
317 POP_TAG();
318 if (state)
319 *state = status;
320 }
321
322 /*
323 * call-seq:
324 * load(filename, wrap=false) => true
325 *
326 * Loads and executes the Ruby
327 * program in the file _filename_. If the filename does not
328 * resolve to an absolute path, the file is searched for in the library
329 * directories listed in <code>$:</code>. If the optional _wrap_
330 * parameter is +true+, the loaded script will be executed
331 * under an anonymous module, protecting the calling program's global
332 * namespace. In no circumstance will any local variables in the loaded
333 * file be propagated to the loading environment.
334 */
335
336 static VALUE
337 rb_f_load(int argc, VALUE *argv)
338 {
339 VALUE fname, wrap;
340
341 rb_scan_args(argc, argv, "11", &fname, &wrap);
342 rb_load(fname, RTEST(wrap));
343 return Qtrue;
344 }
345
346 static char *
347 load_lock(const char *ftptr)
348 {
349 st_data_t data;
350 st_table *loading_tbl = get_loading_table();
351
352 if (!loading_tbl || !st_lookup(loading_tbl, (st_data_t)ftptr, &data)) {
353 /* loading ruby library should be serialized. */
354 if (!loading_tbl) {
a956b91 misc fixes
Laurent Sansonetti authored
355 loading_tbl = st_init_strtable();
356 GC_WB(&GET_VM()->loading_table, loading_tbl);
511dc44 initial import
Laurent Sansonetti authored
357 }
358 /* partial state */
359 ftptr = ruby_strdup(ftptr);
360 data = (st_data_t)rb_barrier_new();
361 st_insert(loading_tbl, (st_data_t)ftptr, data);
362 return (char *)ftptr;
363 }
364 return RTEST(rb_barrier_wait((VALUE)data)) ? (char *)ftptr : 0;
365 }
366
367 static void
368 load_unlock(const char *ftptr)
369 {
370 if (ftptr) {
371 st_data_t key = (st_data_t)ftptr;
372 st_data_t data;
373 st_table *loading_tbl = get_loading_table();
374
375 if (st_delete(loading_tbl, &key, &data)) {
376 xfree((char *)key);
377 rb_barrier_release((VALUE)data);
378 }
379 }
380 }
381
382
383 /*
384 * call-seq:
385 * require(string) => true or false
386 *
387 * Ruby tries to load the library named _string_, returning
388 * +true+ if successful. If the filename does not resolve to
389 * an absolute path, it will be searched for in the directories listed
390 * in <code>$:</code>. If the file has the extension ``.rb'', it is
391 * loaded as a source file; if the extension is ``.so'', ``.o'', or
392 * ``.dll'', or whatever the default shared library extension is on
393 * the current platform, Ruby loads the shared library as a Ruby
394 * extension. Otherwise, Ruby tries adding ``.rb'', ``.so'', and so on
395 * to the name. The name of the loaded feature is added to the array in
396 * <code>$"</code>. A feature will not be loaded if it's name already
397 * appears in <code>$"</code>. However, the file name is not converted
398 * to an absolute path, so that ``<code>require 'a';require
399 * './a'</code>'' will load <code>a.rb</code> twice.
400 *
401 * require "my-library.rb"
402 * require "db-driver"
403 */
404
405 VALUE
406 rb_f_require(VALUE obj, VALUE fname)
407 {
408 return rb_require_safe(fname, rb_safe_level());
409 }
410
26d0e1f merge with ruby trunk r16762 + better/faster objc-like dispatcher
Laurent Sansonetti authored
411 /*static*/ int
511dc44 initial import
Laurent Sansonetti authored
412 search_required(VALUE fname, volatile VALUE *path)
413 {
414 VALUE tmp;
4db9b74 improving perfs, passing more tests, rubygems support wip
Laurent Sansonetti authored
415 const char *ext, *ftptr;
511dc44 initial import
Laurent Sansonetti authored
416 int type, ft = 0;
417 const char *loading;
418
419 *path = 0;
70fef6e RSTRING_PTR/RSTRING_LEN -> RSTRING_BYTEPTR/RSTRING_BYTELEN, RSTRING_C…
Laurent Sansonetti authored
420 ext = strrchr(ftptr = RSTRING_PTR(fname), '.');
511dc44 initial import
Laurent Sansonetti authored
421 if (ext && !strchr(ext, '/')) {
422 if (IS_RBEXT(ext)) {
423 if (rb_feature_p(ftptr, ext, Qtrue, Qfalse, &loading)) {
424 if (loading) *path = rb_str_new2(loading);
425 return 'r';
426 }
427 if ((tmp = rb_find_file(fname)) != 0) {
428 tmp = rb_file_expand_path(tmp, Qnil);
70fef6e RSTRING_PTR/RSTRING_LEN -> RSTRING_BYTEPTR/RSTRING_BYTELEN, RSTRING_C…
Laurent Sansonetti authored
429 ext = strrchr(ftptr = RSTRING_PTR(tmp), '.');
511dc44 initial import
Laurent Sansonetti authored
430 if (!rb_feature_p(ftptr, ext, Qtrue, Qtrue, 0))
431 *path = tmp;
432 return 'r';
433 }
434 return 0;
435 }
436 else if (IS_SOEXT(ext)) {
437 if (rb_feature_p(ftptr, ext, Qfalse, Qfalse, &loading)) {
438 if (loading) *path = rb_str_new2(loading);
439 return 's';
440 }
70fef6e RSTRING_PTR/RSTRING_LEN -> RSTRING_BYTEPTR/RSTRING_BYTELEN, RSTRING_C…
Laurent Sansonetti authored
441 tmp = rb_str_new(RSTRING_PTR(fname), ext - RSTRING_PTR(fname));
511dc44 initial import
Laurent Sansonetti authored
442 #ifdef DLEXT2
443 OBJ_FREEZE(tmp);
444 if (rb_find_file_ext(&tmp, loadable_ext + 1)) {
445 tmp = rb_file_expand_path(tmp, Qnil);
70fef6e RSTRING_PTR/RSTRING_LEN -> RSTRING_BYTEPTR/RSTRING_BYTELEN, RSTRING_C…
Laurent Sansonetti authored
446 ext = strrchr(ftptr = RSTRING_PTR(tmp), '.');
511dc44 initial import
Laurent Sansonetti authored
447 if (!rb_feature_p(ftptr, ext, Qfalse, Qtrue, 0))
448 *path = tmp;
449 return 's';
450 }
451 #else
452 rb_str_cat2(tmp, DLEXT);
453 OBJ_FREEZE(tmp);
454 if ((tmp = rb_find_file(tmp)) != 0) {
455 tmp = rb_file_expand_path(tmp, Qnil);
70fef6e RSTRING_PTR/RSTRING_LEN -> RSTRING_BYTEPTR/RSTRING_BYTELEN, RSTRING_C…
Laurent Sansonetti authored
456 ext = strrchr(ftptr = RSTRING_PTR(tmp), '.');
511dc44 initial import
Laurent Sansonetti authored
457 if (!rb_feature_p(ftptr, ext, Qfalse, Qtrue, 0))
458 *path = tmp;
459 return 's';
460 }
461 #endif
462 }
463 else if (IS_DLEXT(ext)) {
464 if (rb_feature_p(ftptr, ext, Qfalse, Qfalse, &loading)) {
465 if (loading) *path = rb_str_new2(loading);
466 return 's';
467 }
468 if ((tmp = rb_find_file(fname)) != 0) {
469 tmp = rb_file_expand_path(tmp, Qnil);
70fef6e RSTRING_PTR/RSTRING_LEN -> RSTRING_BYTEPTR/RSTRING_BYTELEN, RSTRING_C…
Laurent Sansonetti authored
470 ext = strrchr(ftptr = RSTRING_PTR(tmp), '.');
511dc44 initial import
Laurent Sansonetti authored
471 if (!rb_feature_p(ftptr, ext, Qfalse, Qtrue, 0))
472 *path = tmp;
473 return 's';
474 }
475 }
476 }
477 else if ((ft = rb_feature_p(ftptr, 0, Qfalse, Qfalse, &loading)) == 'r') {
478 if (loading) *path = rb_str_new2(loading);
479 return 'r';
480 }
481 tmp = fname;
482 type = rb_find_file_ext(&tmp, loadable_ext);
483 tmp = rb_file_expand_path(tmp, Qnil);
484 switch (type) {
485 case 0:
486 if (ft)
487 break;
70fef6e RSTRING_PTR/RSTRING_LEN -> RSTRING_BYTEPTR/RSTRING_BYTELEN, RSTRING_C…
Laurent Sansonetti authored
488 ftptr = RSTRING_PTR(tmp);
511dc44 initial import
Laurent Sansonetti authored
489 return rb_feature_p(ftptr, 0, Qfalse, Qtrue, 0);
490
491 default:
492 if (ft)
493 break;
494 case 1:
70fef6e RSTRING_PTR/RSTRING_LEN -> RSTRING_BYTEPTR/RSTRING_BYTELEN, RSTRING_C…
Laurent Sansonetti authored
495 ext = strrchr(ftptr = RSTRING_PTR(tmp), '.');
511dc44 initial import
Laurent Sansonetti authored
496 if (rb_feature_p(ftptr, ext, !--type, Qtrue, &loading) && !loading)
497 break;
498 *path = tmp;
499 }
500 return type ? 's' : 'r';
501 }
502
503 static void
504 load_failed(VALUE fname)
505 {
506 rb_raise(rb_eLoadError, "no such file to load -- %s",
70fef6e RSTRING_PTR/RSTRING_LEN -> RSTRING_BYTEPTR/RSTRING_BYTELEN, RSTRING_C…
Laurent Sansonetti authored
507 RSTRING_PTR(fname));
511dc44 initial import
Laurent Sansonetti authored
508 }
509
510 static VALUE
511 load_ext(VALUE path)
512 {
513 SCOPE_SET(NOEX_PUBLIC);
70fef6e RSTRING_PTR/RSTRING_LEN -> RSTRING_BYTEPTR/RSTRING_BYTELEN, RSTRING_C…
Laurent Sansonetti authored
514 return (VALUE)dln_load(RSTRING_PTR(path));
511dc44 initial import
Laurent Sansonetti authored
515 }
516
517 VALUE
518 rb_require_safe(VALUE fname, int safe)
519 {
520 VALUE result = Qnil;
521 rb_thread_t *th = GET_THREAD();
522 volatile VALUE errinfo = th->errinfo;
523 int state;
524 struct {
525 int safe;
526 } volatile saved;
527 char *volatile ftptr = 0;
528
529 PUSH_TAG();
530 saved.safe = rb_safe_level();
531 if ((state = EXEC_TAG()) == 0) {
532 VALUE path;
533 long handle;
534 int found;
535
536 rb_set_safe_level_force(safe);
eee9d7b sync with ruby trunk r15665
Laurent Sansonetti authored
537 FilePathValue(fname);
538 RB_GC_GUARD(fname) = rb_str_new4(fname);
511dc44 initial import
Laurent Sansonetti authored
539 found = search_required(fname, &path);
540 if (found) {
70fef6e RSTRING_PTR/RSTRING_LEN -> RSTRING_BYTEPTR/RSTRING_BYTELEN, RSTRING_C…
Laurent Sansonetti authored
541 if (!path || !(ftptr = load_lock(RSTRING_PTR(path)))) {
511dc44 initial import
Laurent Sansonetti authored
542 result = Qfalse;
543 }
544 else {
545 rb_set_safe_level_force(0);
546 switch (found) {
547 case 'r':
548 rb_load(path, 0);
549 break;
550
551 case 's':
552 handle = (long)rb_vm_call_cfunc(rb_vm_top_self(), load_ext,
553 path, 0, path);
554 rb_ary_push(ruby_dln_librefs, LONG2NUM(handle));
555 break;
556 }
557 rb_provide_feature(path);
558 result = Qtrue;
559 }
560 }
561 }
562 POP_TAG();
563 load_unlock(ftptr);
564
565 rb_set_safe_level_force(saved.safe);
566 if (state) {
567 JUMP_TAG(state);
568 }
569
570 if (NIL_P(result)) {
571 load_failed(fname);
572 }
573
6043d94 more missing wb, yeepee
Laurent Sansonetti authored
574 GC_WB(&th->errinfo, errinfo);
511dc44 initial import
Laurent Sansonetti authored
575
576 return result;
577 }
578
579 VALUE
580 rb_require(const char *fname)
581 {
582 VALUE fn = rb_str_new2(fname);
583 OBJ_FREEZE(fn);
584 return rb_require_safe(fn, rb_safe_level());
585 }
586
587 static VALUE
588 init_ext_call(VALUE arg)
589 {
590 SCOPE_SET(NOEX_PUBLIC);
591 (*(void (*)(void))arg)();
592 return Qnil;
593 }
594
595 void
596 ruby_init_ext(const char *name, void (*init)(void))
597 {
598 if (load_lock(name)) {
599 rb_vm_call_cfunc(rb_vm_top_self(), init_ext_call, (VALUE)init,
600 0, rb_str_new2(name));
601 rb_provide(name);
602 load_unlock(name);
603 }
604 }
605
606 /*
607 * call-seq:
608 * mod.autoload(name, filename) => nil
609 *
610 * Registers _filename_ to be loaded (using <code>Kernel::require</code>)
611 * the first time that _module_ (which may be a <code>String</code> or
612 * a symbol) is accessed in the namespace of _mod_.
613 *
614 * module A
615 * end
616 * A.autoload(:B, "b")
617 * A::B.doit # autoloads "b"
618 */
619
620 static VALUE
621 rb_mod_autoload(VALUE mod, VALUE sym, VALUE file)
622 {
623 ID id = rb_to_id(sym);
624
625 Check_SafeStr(file);
70fef6e RSTRING_PTR/RSTRING_LEN -> RSTRING_BYTEPTR/RSTRING_BYTELEN, RSTRING_C…
Laurent Sansonetti authored
626 rb_autoload(mod, id, RSTRING_PTR(file));
511dc44 initial import
Laurent Sansonetti authored
627 return Qnil;
628 }
629
630 /*
631 * MISSING: documentation
632 */
633
634 static VALUE
635 rb_mod_autoload_p(VALUE mod, VALUE sym)
636 {
637 return rb_autoload_p(mod, rb_to_id(sym));
638 }
639
640 /*
641 * call-seq:
642 * autoload(module, filename) => nil
643 *
644 * Registers _filename_ to be loaded (using <code>Kernel::require</code>)
645 * the first time that _module_ (which may be a <code>String</code> or
646 * a symbol) is accessed.
647 *
648 * autoload(:MyModule, "/usr/local/lib/modules/my_module.rb")
649 */
650
651 static VALUE
652 rb_f_autoload(VALUE obj, VALUE sym, VALUE file)
653 {
26d0e1f merge with ruby trunk r16762 + better/faster objc-like dispatcher
Laurent Sansonetti authored
654 VALUE klass = rb_vm_cbase();
511dc44 initial import
Laurent Sansonetti authored
655 if (NIL_P(klass)) {
656 rb_raise(rb_eTypeError, "Can not set autoload on singleton class");
657 }
658 return rb_mod_autoload(klass, sym, file);
659 }
660
661 /*
662 * MISSING: documentation
663 */
664
665 static VALUE
666 rb_f_autoload_p(VALUE obj, VALUE sym)
667 {
26d0e1f merge with ruby trunk r16762 + better/faster objc-like dispatcher
Laurent Sansonetti authored
668 /* use rb_vm_cbase() as same as rb_f_autoload. */
669 VALUE klass = rb_vm_cbase();
511dc44 initial import
Laurent Sansonetti authored
670 if (NIL_P(klass)) {
671 return Qnil;
672 }
673 return rb_mod_autoload_p(klass, sym);
674 }
675
676 void
677 Init_load()
678 {
eee9d7b sync with ruby trunk r15665
Laurent Sansonetti authored
679 rb_vm_t *vm = GET_VM();
680 const char *var_load_path = "$:";
681 ID id_load_path = rb_intern(var_load_path);
682
683 rb_define_hooked_variable(var_load_path, (VALUE*)GET_VM(), load_path_getter, 0);
684 rb_alias_variable((rb_intern)("$-I"), id_load_path);
685 rb_alias_variable((rb_intern)("$LOAD_PATH"), id_load_path);
686 vm->load_path = rb_ary_new();
511dc44 initial import
Laurent Sansonetti authored
687
688 rb_define_virtual_variable("$\"", get_loaded_features, 0);
689 rb_define_virtual_variable("$LOADED_FEATURES", get_loaded_features, 0);
26d0e1f merge with ruby trunk r16762 + better/faster objc-like dispatcher
Laurent Sansonetti authored
690 GC_WB(&vm->loaded_features, rb_ary_new());
511dc44 initial import
Laurent Sansonetti authored
691
692 rb_define_global_function("load", rb_f_load, -1);
693 rb_define_global_function("require", rb_f_require, 1);
694 rb_define_method(rb_cModule, "autoload", rb_mod_autoload, 2);
695 rb_define_method(rb_cModule, "autoload?", rb_mod_autoload_p, 1);
696 rb_define_global_function("autoload", rb_f_autoload, 2);
697 rb_define_global_function("autoload?", rb_f_autoload_p, 1);
698
699 #if WITH_OBJC
77169a8 Kernel#framework(path) becomes Kernel#framework(path, search_network=…
Laurent Sansonetti authored
700 rb_define_global_function("framework", rb_require_framework, -1);
511dc44 initial import
Laurent Sansonetti authored
701 #endif
702
703 ruby_dln_librefs = rb_ary_new();
704 GC_ROOT(&ruby_dln_librefs);
705 rb_register_mark_object(ruby_dln_librefs);
706 }
Something went wrong with that request. Please try again.