e$B1sF#$G$9!#e(B
2010e$BG/e(B3e$B7ne(B8e$BF|e(B13:22 Tanaka A. [email protected]:
p caller(0)
% ruby – -e
[“-e:1:in `'”]
e$B$$H$J$7$/e(B C
e$B$G<BAu$7$F$_$^$7$?!#%U%!%$%k$+$i%m!<%I$7$?>l9g$K8B$j!"e(B
rb_iseq_t e$B$K@dBP%Q%9$r:$;$F$$-$^$9!#e(B
e$B$3$N%A%1%C%H$N:G=i$NNc$,2r7h$7!"e(B-e
e$B$NNc$b0J2<$N$h$&$K$J$j$^$9!#e(B
$ ./ruby -e ‘require_relative “lib/cgi”’
-e:1:in require_relative': cannot infer basepath (LoadError) from -e:1:in
’
$ cat ./-e
require_relative “lib/cgi”
$ ./ruby – -e
e$BH?BP$,$J$5$=$&$J$i%3%_%C%H$7$h$&$H;W$$$^$9!#e(B
diff --git a/compile.c b/compile.c
index ad57ca2…f37fbd8 100644
— a/compile.c
+++ b/compile.c
@@ -169,6 +169,9 @@ PRINTF_ARGS(void ruby_debug_printf(const char*,
…), 1, 2);
#define iseq_filename(iseq)
(((rb_iseq_t*)DATA_PTR(iseq))->filename)
+#define iseq_filepath(iseq) \
- (((rb_iseq_t*)DATA_PTR(iseq))->filepath)
-
#define NEW_ISEQVAL(node, name, type, line_no)
new_child_iseq(iseq, node, name, 0, type, line_no)
@@ -917,7 +920,7 @@ new_child_iseq(rb_iseq_t *iseq, NODE *node,
VALUE ret;
debugs("[new_child_iseq]>
---------------------------------------\n");
- ret = rb_iseq_new_with_opt(node, name, iseq_filename(iseq->self),
INT2FIX(line_no),
- ret = rb_iseq_new_with_opt(node, name, iseq_filename(iseq->self),
iseq_filepath(iseq->self), INT2FIX(line_no),
parent, type, iseq->compile_data->option);
debugs(“[new_child_iseq]<
---------------------------------------\n”);
iseq_add_mark_object(iseq, ret);
diff --git a/file.c b/file.c
index 50516ad…f381f55 100644
— a/file.c
+++ b/file.c
@@ -3165,8 +3165,8 @@ realpath_rec(long *prefixlenp, VALUE *resolvedp,
char *unresolved, VALUE loopche
}
}
-static VALUE
-realpath_internal(VALUE basedir, VALUE path, int strict)
+VALUE
+rb_realpath_internal(VALUE basedir, VALUE path, int strict)
{
long prefixlen;
VALUE resolved;
@@ -3244,7 +3244,7 @@ rb_file_s_realpath(int argc, VALUE *argv, VALUE
klass)
{
VALUE path, basedir;
rb_scan_args(argc, argv, “11”, &path, &basedir);
- return realpath_internal(basedir, path, 1);
- return rb_realpath_internal(basedir, path, 1);
}
/*
@@ -3264,7 +3264,7 @@ rb_file_s_realdirpath(int argc, VALUE *argv, VALUE
klass)
{
VALUE path, basedir;
rb_scan_args(argc, argv, “11”, &path, &basedir);
- return realpath_internal(basedir, path, 0);
- return rb_realpath_internal(basedir, path, 0);
}
static size_t
@@ -3390,7 +3390,7 @@ rb_file_s_basename(int argc, VALUE *argv)
“/home/gumby/work”
*/
-static VALUE
+VALUE
rb_file_s_dirname(VALUE klass, VALUE fname)
{
const char *name, *root, *p;
diff --git a/iseq.c b/iseq.c
index 80364ca…4007913 100644
— a/iseq.c
+++ b/iseq.c
@@ -98,6 +98,7 @@ iseq_mark(void *ptr)
RUBY_MARK_UNLESS_NULL(iseq->mark_ary);
RUBY_MARK_UNLESS_NULL(iseq->name);
RUBY_MARK_UNLESS_NULL(iseq->filename);
- RUBY_MARK_UNLESS_NULL(iseq->filepath);
RUBY_MARK_UNLESS_NULL((VALUE)iseq->cref_stack);
RUBY_MARK_UNLESS_NULL(iseq->klass);
RUBY_MARK_UNLESS_NULL(iseq->coverage);
@@ -207,9 +208,11 @@ set_relation(rb_iseq_t *iseq, const VALUE parent)
}
}
+VALUE rb_realpath_internal(VALUE basedir, VALUE path, int strict);
+
static VALUE
prepare_iseq_build(rb_iseq_t *iseq,
-
VALUE name, VALUE filename, VALUE filepath, VALUE line_no,
VALUE parent, VALUE type, VALUE block_opt,
const rb_compile_option_t *option)
{
@@ -218,6 +221,7 @@ prepare_iseq_build(rb_iseq_t *iseq,
iseq->name = name;
iseq->filename = filename;
- iseq->filepath = filepath == Qnil ? Qnil :
rb_realpath_internal(Qnil, filepath, 1);
iseq->line_no = line_no;
iseq->defined_method_id = 0;
iseq->mark_ary = rb_ary_tmp_new(3);
@@ -361,31 +365,31 @@ make_compile_option_value(rb_compile_option_t
*option)
}
VALUE
-rb_iseq_new(NODE *node, VALUE name, VALUE filename,
+rb_iseq_new(NODE *node, VALUE name, VALUE filename, VALUE filepath,
VALUE parent, VALUE type)
{
- return rb_iseq_new_with_opt(node, name, filename, INT2FIX(0),
parent, type,
- return rb_iseq_new_with_opt(node, name, filename, filepath,
INT2FIX(0), parent, type,
&COMPILE_OPTION_DEFAULT);
}
VALUE
-rb_iseq_new_top(NODE *node, VALUE name, VALUE filename, VALUE parent)
+rb_iseq_new_top(NODE *node, VALUE name, VALUE filename, VALUE
filepath, VALUE parent)
{
- return rb_iseq_new_with_opt(node, name, filename, INT2FIX(0),
parent, ISEQ_TYPE_TOP,
- return rb_iseq_new_with_opt(node, name, filename, filepath,
INT2FIX(0), parent, ISEQ_TYPE_TOP,
&COMPILE_OPTION_DEFAULT);
}
VALUE
-rb_iseq_new_main(NODE *node, VALUE filename)
+rb_iseq_new_main(NODE *node, VALUE filename, VALUE filepath)
{
rb_thread_t *th = GET_THREAD();
VALUE parent = th->base_block->iseq->self;
- return rb_iseq_new_with_opt(node, rb_str_new2(“”),
filename, INT2FIX(0),
- return rb_iseq_new_with_opt(node, rb_str_new2(“”),
filename, filepath, INT2FIX(0),
parent, ISEQ_TYPE_MAIN, &COMPILE_OPTION_DEFAULT);
}
static VALUE
-rb_iseq_new_with_bopt_and_opt(NODE *node, VALUE name, VALUE filename,
VALUE line_no,
+rb_iseq_new_with_bopt_and_opt(NODE *node, VALUE name, VALUE filename,
VALUE filepath, VALUE line_no,
VALUE parent, VALUE type, VALUE bopt,
const rb_compile_option_t *option)
{
@@ -395,28 +399,28 @@ rb_iseq_new_with_bopt_and_opt(NODE *node, VALUE
name, VALUE filename, VALUE line
GetISeqPtr(self, iseq);
iseq->self = self;
- prepare_iseq_build(iseq, name, filename, line_no, parent, type,
bopt, option);
- prepare_iseq_build(iseq, name, filename, filepath, line_no,
parent, type, bopt, option);
rb_iseq_compile_node(self, node);
cleanup_iseq_build(iseq);
return self;
}
VALUE
-rb_iseq_new_with_opt(NODE *node, VALUE name, VALUE filename, VALUE
line_no,
+rb_iseq_new_with_opt(NODE *node, VALUE name, VALUE filename, VALUE
filepath, VALUE line_no,
VALUE parent, VALUE type,
const rb_compile_option_t option)
{
/ TODO: argument check */
- return rb_iseq_new_with_bopt_and_opt(node, name, filename,
line_no, parent, type,
- return rb_iseq_new_with_bopt_and_opt(node, name, filename,
filepath, line_no, parent, type,
Qfalse, option);
}
VALUE
-rb_iseq_new_with_bopt(NODE *node, VALUE name, VALUE filename, VALUE
line_no,
+rb_iseq_new_with_bopt(NODE node, VALUE name, VALUE filename, VALUE
filepath, VALUE line_no,
VALUE parent, VALUE type, VALUE bopt)
{
/ TODO: argument check */
- return rb_iseq_new_with_bopt_and_opt(node, name, filename,
line_no, parent, type,
- return rb_iseq_new_with_bopt_and_opt(node, name, filename,
filepath, line_no, parent, type,
bopt, &COMPILE_OPTION_DEFAULT);
}
@@ -430,7 +434,7 @@ iseq_load(VALUE self, VALUE data, VALUE parent,
VALUE opt)
VALUE iseqval = iseq_alloc(self);
VALUE magic, version1, version2, format_type, misc;
- VALUE name, filename, line_no;
-
VALUE name, filename, filepath, line_no;
VALUE type, body, locals, args, exception;
VALUE iseq_type;
@@ -454,6 +458,7 @@ iseq_load(VALUE self, VALUE data, VALUE parent,
VALUE opt)
name = CHECK_STRING(rb_ary_entry(data, i++));
filename = CHECK_STRING(rb_ary_entry(data, i++));
-
filepath = CHECK_STRING(rb_ary_entry(data, i++));
line_no = CHECK_INTEGER(rb_ary_entry(data, i++));
type = CHECK_SYMBOL(rb_ary_entry(data, i++));
@@ -496,7 +501,7 @@ iseq_load(VALUE self, VALUE data, VALUE parent,
VALUE opt)
}
make_compile_option(&option, opt);
- prepare_iseq_build(iseq, name, filename, line_no,
-
prepare_iseq_build(iseq, name, filename, filepath, line_no,
parent, iseq_type, 0, &option);
rb_iseq_build_from_ary(iseq, locals, args, exception, body);
@@ -533,7 +538,7 @@ parse_string(VALUE str, const char *file, int line)
}
VALUE
-rb_iseq_compile_with_option(VALUE src, VALUE file, VALUE line, VALUE
opt)
+rb_iseq_compile_with_option(VALUE src, VALUE file, VALUE filepath,
VALUE line, VALUE opt)
{
rb_compile_option_t option;
const char *fn = StringValueCStr(file);
@@ -544,11 +549,11 @@ rb_iseq_compile_with_option(VALUE src, VALUE
file, VALUE line, VALUE opt)
if (th->base_block && th->base_block->iseq) {
return rb_iseq_new_with_opt(node, th->base_block->iseq->name,
-
file, filepath, line, th->base_block->iseq->self,
ISEQ_TYPE_EVAL, &option);
}
else {
- return rb_iseq_new_with_opt(node, rb_str_new2(“”), file,
line, Qfalse,
- return rb_iseq_new_with_opt(node, rb_str_new2(“”), file,
filepath, line, Qfalse,
ISEQ_TYPE_TOP, &option);
}
}
@@ -556,21 +561,21 @@ rb_iseq_compile_with_option(VALUE src, VALUE
file, VALUE line, VALUE opt)
VALUE
rb_iseq_compile(VALUE src, VALUE file, VALUE line)
{
- return rb_iseq_compile_with_option(src, file, line, Qnil);
- return rb_iseq_compile_with_option(src, file, Qnil, line, Qnil);
}
static VALUE
iseq_s_compile(int argc, VALUE *argv, VALUE self)
{
- VALUE src, file = Qnil, line = INT2FIX(1), opt = Qnil;
-
VALUE src, file = Qnil, path = Qnil, line = INT2FIX(1), opt = Qnil;
rb_secure(1);
- rb_scan_args(argc, argv, “13”, &src, &file, &line, &opt);
- rb_scan_args(argc, argv, “13”, &src, &file, &path, &line, &opt);
if (NIL_P(file)) file = rb_str_new2(“”);
if (NIL_P(line)) line = INT2FIX(1);
- return rb_iseq_compile_with_option(src, file, line, opt);
- return rb_iseq_compile_with_option(src, file, path, line, opt);
}
static VALUE
@@ -593,7 +598,7 @@ iseq_s_compile_file(int argc, VALUE *argv, VALUE
self)
parser = rb_parser_new();
node = rb_parser_compile_file(parser, fname, f, NUM2INT(line));
make_compile_option(&option, opt);
- return rb_iseq_new_with_opt(node, rb_str_new2(“”), file,
line, Qfalse,
- return rb_iseq_new_with_opt(node, rb_str_new2(“”), file,
file, line, Qfalse,
ISEQ_TYPE_TOP, &option);
}
@@ -1311,7 +1316,7 @@ iseq_data_to_ary(rb_iseq_t *iseq)
/*
* [:magic, :major_version, :minor_version, :format_type, :misc,
-
* :name, :filename, :line_no, :type, :locals, :args,
-
* :name, :filename, :filepath, :line_no, :type, :locals, :args,
* :catch_table, :bytecode]
*/
rb_ary_push(val,
rb_str_new2(“YARVInstructionSequence/SimpleDataFormat”));
@@ -1321,6 +1326,7 @@ iseq_data_to_ary(rb_iseq_t *iseq)
rb_ary_push(val, misc);
rb_ary_push(val, iseq->name);
rb_ary_push(val, iseq->filename);
- rb_ary_push(val, iseq->filepath);
rb_ary_push(val, iseq->line_no);
rb_ary_push(val, type);
rb_ary_push(val, locals);
diff --git a/load.c b/load.c
index 7551b6b…c532544 100644
— a/load.c
+++ b/load.c
@@ -288,7 +288,7 @@ rb_load_internal(VALUE fname, int wrap)
th->mild_compile_error++;
node = (NODE *)rb_load_file(RSTRING_PTR(fname));
loaded = TRUE;
- iseq = rb_iseq_new_top(node, rb_str_new2(“<top (required)>”), fname,
Qfalse);
- iseq = rb_iseq_new_top(node, rb_str_new2(“<top (required)>”), fname,
fname, Qfalse);
th->mild_compile_error–;
rb_iseq_eval(iseq);
}
@@ -439,6 +439,19 @@ rb_f_require(VALUE obj, VALUE fname)
return rb_require_safe(fname, rb_safe_level());
}
+VALUE
+rb_f_require_relative(VALUE obj, VALUE fname)
+{
- VALUE rb_current_realfilepath(void);
- VALUE rb_file_s_dirname(VALUE klass, VALUE fname);
- VALUE base = rb_current_realfilepath();
- if (NIL_P(base)) {
- rb_raise(rb_eLoadError, “cannot infer basepath”);
- }
- base = rb_file_s_dirname(rb_cFile, base);
- return rb_require_safe(rb_file_expand_path(fname, base),
rb_safe_level());
+}
-
static int
search_required(VALUE fname, volatile VALUE *path, int safe_level)
{
@@ -734,6 +747,7 @@ Init_load()
rb_define_global_function("load", rb_f_load, -1);
rb_define_global_function("require", rb_f_require, 1);
- rb_define_global_function(“require_relative”,
rb_f_require_relative, 1);
rb_define_method(rb_cModule, “autoload”, rb_mod_autoload, 2);
rb_define_method(rb_cModule, “autoload?”, rb_mod_autoload_p, 1);
rb_define_global_function(“autoload”, rb_f_autoload, 2);
diff --git a/prelude.rb b/prelude.rb
index 679e831…1d084df 100644
— a/prelude.rb
+++ b/prelude.rb
@@ -22,17 +22,3 @@ class Thread
}
end
end
-module Kernel
-
module_function
-
def require_relative(relative_feature)
-
c = caller.first
-
e = c.rindex(/:\d+:in /)
-
file = $`
-
if /\A((.*))/ =~ file # eval, etc.
-
raise LoadError, "require_relative is called in #{$1}"
-
end
-
absolute_feature = File.join(File.dirname(File.realpath(file)),
relative_feature)
-
require absolute_feature
-
end
-end
diff --git a/ruby.c b/ruby.c
index 5367720…a7353a9 100644
— a/ruby.c
+++ b/ruby.c
@@ -1445,7 +1445,9 @@ process_options(int argc, char **argv, struct
cmdline_options *opt)
}
PREPARE_PARSE_MAIN({
-
iseq = rb_iseq_new_main(tree, opt->script_name);
-
VALUE path = Qnil;
-
if (!opt->e_script && strcmp(opt->script, “-”)) path =
opt->script_name;
-
iseq = rb_iseq_new_main(tree, opt->script_name, path);
});
if (opt->dump & DUMP_BIT(insns)) {
diff --git a/vm.c b/vm.c
index 96a04bf…678fcb8 100644
— a/vm.c
+++ b/vm.c
@@ -1441,7 +1441,7 @@ rb_vm_call_cfunc(VALUE recv, VALUE
(*func)(VALUE), VALUE arg,
{
rb_thread_t *th = GET_THREAD();
const rb_control_frame_t *reg_cfp = th->cfp;
- volatile VALUE iseqval = rb_iseq_new(0, filename, filename, 0,
ISEQ_TYPE_TOP);
-
volatile VALUE iseqval = rb_iseq_new(0, filename, filename,
filename, 0, ISEQ_TYPE_TOP);
VALUE val;
vm_push_frame(th, DATA_PTR(iseqval), VM_FRAME_MAGIC_TOP,
@@ -2052,7 +2052,7 @@ Init_VM(void)
rb_vm_t *vm = ruby_current_vm;
rb_thread_t *th = GET_THREAD();
VALUE filename = rb_str_new2(“”);
- volatile VALUE iseqval = rb_iseq_new(0, filename, filename, 0,
ISEQ_TYPE_TOP);
- volatile VALUE iseqval = rb_iseq_new(0, filename, filename, Qnil, 0,
ISEQ_TYPE_TOP);
volatile VALUE th_self;
rb_iseq_t *iseq;
diff --git a/vm_core.h b/vm_core.h
index 126f48e…7bf199b 100644
— a/vm_core.h
+++ b/vm_core.h
@@ -155,6 +155,7 @@ struct rb_iseq_struct {
VALUE type; /* instruction sequence type /
VALUE name; / String: iseq name /
VALUE filename; / file information where this sequence from
*/
- VALUE filepath; /* real file path or nil */
VALUE iseq; / iseq (insn number and openrads) */
VALUE iseq_encoded; / encoded iseq */
unsigned long iseq_size;
@@ -464,11 +465,11 @@ typedef struct rb_thread_struct
} rb_thread_t;
/* iseq.c /
-VALUE rb_iseq_new(NODE, VALUE, VALUE, VALUE, VALUE);
-VALUE rb_iseq_new_top(NODE node, VALUE name, VALUE filename, VALUE
parent);
-VALUE rb_iseq_new_main(NODE node, VALUE filename);
-VALUE rb_iseq_new_with_bopt(NODE, VALUE, VALUE, VALUE, VALUE, VALUE,
VALUE);
-VALUE rb_iseq_new_with_opt(NODE, VALUE, VALUE, VALUE, VALUE, VALUE,
const rb_compile_option_t*);
+VALUE rb_iseq_new(NODE*, VALUE, VALUE, VALUE, VALUE, VALUE);
+VALUE rb_iseq_new_top(NODE node, VALUE name, VALUE filename, VALUE
filepath, VALUE parent);
+VALUE rb_iseq_new_main(NODE node, VALUE filename, VALUE filepath);
+VALUE rb_iseq_new_with_bopt(NODE, VALUE, VALUE, VALUE, VALUE, VALUE,
VALUE, VALUE);
+VALUE rb_iseq_new_with_opt(NODE, VALUE, VALUE, VALUE, VALUE, VALUE,
VALUE, const rb_compile_option_t*);
VALUE rb_iseq_compile(VALUE src, VALUE file, VALUE line);
VALUE rb_iseq_disasm(VALUE self);
int rb_iseq_disasm_insn(VALUE str, VALUE *iseqval, size_t pos,
rb_iseq_t *iseq, VALUE child);
diff --git a/vm_eval.c b/vm_eval.c
index 2e011c7…0ce4b8f 100644
— a/vm_eval.c
+++ b/vm_eval.c
@@ -1709,6 +1709,16 @@ rb_f_block_given_p(void)
}
}
+VALUE
+rb_current_realfilepath(void)
+{
- rb_thread_t *th = GET_THREAD();
- rb_control_frame_t *cfp = th->cfp;
- cfp = vm_get_ruby_level_caller_cfp(th,
RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp));
- if (cfp != 0) return cfp->iseq->filepath;
- return Qnil;
+}
-
void
Init_vm_eval(void)
{
e$B$"$-$i$a5$L#$J$N$G$3$C$=$j8@$$$^$9$,!"e(B$: e$B$+$ie(B “.”
e$B$r>J$/$h$&$J;EMMe(B
e$BJQ99$re(B 1.9 e$B7ONsCf$G9T$&$N$OHr$1$k$Y$-$@$H;W$C$F$$$^$9!#e(B