summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog9
-rw-r--r--include/ruby/intern.h1
-rw-r--r--ruby.c10
-rwxr-xr-xtool/compile_prelude.rb222
-rw-r--r--variable.c11
5 files changed, 172 insertions, 81 deletions
diff --git a/ChangeLog b/ChangeLog
index 9a01e0b3f8..83854f2fde 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+Fri Mar 12 07:15:08 2010 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ruby.c (ruby_init_loadpath_safe, ruby_init_gems): set and remove
+ TMP_RUBY_PREFIX.
+
+ * variable.c (rb_mod_remove_const): new function.
+
+ * tool/compile_prelude.rb: split each preludes.
+
Fri Mar 12 07:09:20 2010 Nobuyoshi Nakada <nobu@ruby-lang.org>
* Makefile.in (config.status): setup MINIRUBY environment for
diff --git a/include/ruby/intern.h b/include/ruby/intern.h
index ebbdd713b2..61f642b06a 100644
--- a/include/ruby/intern.h
+++ b/include/ruby/intern.h
@@ -817,6 +817,7 @@ VALUE rb_const_get(VALUE, ID);
VALUE rb_const_get_at(VALUE, ID);
VALUE rb_const_get_from(VALUE, ID);
void rb_const_set(VALUE, ID, VALUE);
+VALUE rb_const_remove(VALUE, ID);
VALUE rb_mod_const_missing(VALUE,VALUE);
VALUE rb_cvar_defined(VALUE, ID);
void rb_cvar_set(VALUE, ID, VALUE);
diff --git a/ruby.c b/ruby.c
index 536772032b..fdca44593d 100644
--- a/ruby.c
+++ b/ruby.c
@@ -358,7 +358,7 @@ ruby_init_loadpath_safe(int safe_level)
#if defined _WIN32 || defined __CYGWIN__
# if VARIABLE_LIBPATH
- sopath = rb_str_tmp_new(MAXPATHLEN);
+ sopath = rb_str_new(0, MAXPATHLEN);
libpath = RSTRING_PTR(sopath);
GetModuleFileName(libruby, libpath, MAXPATHLEN);
# else
@@ -390,7 +390,7 @@ ruby_init_loadpath_safe(int safe_level)
const int win_to_posix = CCP_WIN_A_TO_POSIX | CCP_RELATIVE;
size_t newsize = cygwin_conv_path(win_to_posix, libpath, 0, 0);
if (newsize > 0) {
- VALUE rubylib = rb_str_tmp_new(newsize);
+ VALUE rubylib = rb_str_new(0, newsize);
p = RSTRING_PTR(rubylib);
if (cygwin_conv_path(win_to_posix, libpath, p, newsize) == 0) {
rb_str_resize(sopath, 0);
@@ -418,8 +418,10 @@ ruby_init_loadpath_safe(int safe_level)
strlcpy(libpath, ".", sizeof(libpath));
p = libpath + 1;
}
+#define PREFIX_PATH() rb_str_new(libpath, baselen)
#else
rb_str_set_len(sopath, p - libpath);
+#define PREFIX_PATH() sopath
#endif
baselen = p - libpath;
@@ -428,6 +430,7 @@ ruby_init_loadpath_safe(int safe_level)
#define RUBY_RELATIVE(path, len) rb_str_buf_cat(BASEPATH(), path, len)
#else
#define RUBY_RELATIVE(path, len) rubylib_mangled_path(path, len)
+#define PREFIX_PATH() rubylib_mangled_path(RUBY_LIB_PREFIX, sizeof(RUBY_LIB_PREFIX)-1)
#endif
#define incpush(path) rb_ary_push(load_path, (path))
load_path = GET_VM()->load_path;
@@ -441,6 +444,8 @@ ruby_init_loadpath_safe(int safe_level)
incpush(RUBY_RELATIVE(paths, len));
paths += len + 1;
}
+
+ rb_const_set(rb_cObject, rb_intern_const("TMP_RUBY_PREFIX"), rb_obj_freeze(PREFIX_PATH()));
}
@@ -1086,6 +1091,7 @@ ruby_init_gems(int enable)
{
if (enable) rb_define_module("Gem");
Init_prelude();
+ rb_const_remove(rb_cObject, rb_intern_const("TMP_RUBY_PREFIX"));
}
static int
diff --git a/tool/compile_prelude.rb b/tool/compile_prelude.rb
index 7476e3910f..93a6dd9cf0 100755
--- a/tool/compile_prelude.rb
+++ b/tool/compile_prelude.rb
@@ -4,108 +4,170 @@
# Since $(BASERUBY) may be older than Ruby 1.9,
# Ruby 1.9 feature should not be used.
-$:.unshift(File.expand_path("../..", __FILE__))
+require 'erb'
-preludes = ARGV.dup
-outfile = preludes.pop
-init_name = outfile[/\w+(?=_prelude.c\b)/] || 'prelude'
+class Prelude
+ SRCDIR = File.dirname(File.dirname(__FILE__))
+ $:.unshift(SRCDIR)
-C_ESC = {
- "\\" => "\\\\",
- '"' => '\"',
- "\n" => '\n',
-}
+ C_ESC = {
+ "\\" => "\\\\",
+ '"' => '\"',
+ "\n" => '\n',
+ }
-0x00.upto(0x1f) {|ch| C_ESC[[ch].pack("C")] ||= "\\%03o" % ch }
-0x7f.upto(0xff) {|ch| C_ESC[[ch].pack("C")] = "\\%03o" % ch }
-C_ESC_PAT = Regexp.union(*C_ESC.keys)
+ 0x00.upto(0x1f) {|ch| C_ESC[[ch].pack("C")] ||= "\\%03o" % ch }
+ 0x7f.upto(0xff) {|ch| C_ESC[[ch].pack("C")] = "\\%03o" % ch }
+ C_ESC_PAT = Regexp.union(*C_ESC.keys)
-def c_esc(str)
- '"' + str.gsub(C_ESC_PAT) { C_ESC[$&] } + '"'
-end
-def prelude_name(*path_nests)
- prelude = path_nests.map{|prelude_path| File.basename(prelude_path, ".rb") }.join(":")
- "<internal:" + prelude + ">"
-end
+ def c_esc(str)
+ '"' + str.gsub(C_ESC_PAT) { C_ESC[$&] } + '"'
+ end
+ def prelude_base(filename)
+ filename[/\A#{Regexp.quote(SRCDIR)}\/(.*?)(\.rb)?\z/om, 1]
+ end
+ def prelude_name(filename)
+ "<internal:" + prelude_base(filename) + ">"
+ end
-mkconf = nil
-setup_ruby_prefix = nil
-teardown_ruby_prefix = nil
-lines_list = preludes.map {|filename|
- lines = []
- need_ruby_prefix = false
- File.readlines(filename).each {|line|
- line.gsub!(/RbConfig::CONFIG\["(\w+)"\]/) {
- key = $1
- unless mkconf
- require './rbconfig'
- mkconf = RbConfig::MAKEFILE_CONFIG.merge('prefix'=>'#{TMP_RUBY_PREFIX}')
- setup_ruby_prefix = "TMP_RUBY_PREFIX = $:.reverse.find{|e|e!=\".\"}.sub(%r{(.*)/lib/.*}m, \"\\\\1\")\n"
- teardown_ruby_prefix = 'Object.class_eval { remove_const "TMP_RUBY_PREFIX" }'
- end
- if RbConfig::MAKEFILE_CONFIG.has_key? key
- val = RbConfig.expand("$(#{key})", mkconf)
- need_ruby_prefix = true if /\A\#\{TMP_RUBY_PREFIX\}/ =~ val
- c_esc(val)
- else
- "nil"
- end
- }
- if /require\s*\(?\s*(["'])(.*?)\1\s*\)?/ =~ line
- orig, path = $&, $2
- srcdir = File.expand_path("../..", __FILE__)
- path = File.expand_path(path, srcdir)
- if File.exist?(path)
- lines << c_esc("eval(")
- File.readlines(path).each do |line|
- lines << c_esc(line.dump)
+ def initialize(preludes)
+ @mkconf = nil
+ @have_sublib = false
+ @need_ruby_prefix = false
+ @preludes = {}
+ @mains = preludes.map {|filename| translate(filename)[0]}
+ end
+
+ def translate(filename, sub = false)
+ idx = @preludes[filename]
+ return idx if idx
+ lines = []
+ @preludes[filename] = result = [@preludes.size, filename, lines, sub]
+ File.readlines(filename).each do |line|
+ line.gsub!(/RbConfig::CONFIG\["(\w+)"\]/) {
+ key = $1
+ unless @mkconf
+ require './rbconfig'
+ @mkconf = RbConfig::MAKEFILE_CONFIG.merge('prefix'=>'#{TMP_RUBY_PREFIX}')
+ end
+ if RbConfig::MAKEFILE_CONFIG.has_key? key
+ val = RbConfig.expand("$(#{key})", @mkconf)
+ @need_ruby_prefix ||= /\A\#\{TMP_RUBY_PREFIX\}/ =~ val
+ c_esc(val)
+ else
+ "nil"
+ end
+ }
+ line.sub!(/require\s*\(?\s*(["'])(.*?)\1\)?/) do
+ orig, path = $&, $2
+ path = File.join(SRCDIR, path)
+ if File.exist?(path)
+ @have_sublib = true
+ "TMP_RUBY_PREFIX.require(#{translate(path, true)[0]})"
+ else
+ orig
end
- lines << c_esc(", TOPLEVEL_BINDING, %s, %d)" % [ prelude_name(filename, path).dump, 1])
- else
- lines << c_esc(orig)
end
- else
lines << c_esc(line)
end
- }
- setup_lines = []
- if need_ruby_prefix
- setup_lines << c_esc(setup_ruby_prefix)
- lines << c_esc(teardown_ruby_prefix)
+ result
end
- [setup_lines, lines]
-}
-
-require 'erb'
-tmp = ERB.new(<<'EOS', nil, '%').result(binding)
+ def emit(outfile)
+ init_name = outfile[/\w+(?=_prelude.c\b)/] || 'prelude'
+ erb = ERB.new(<<'EOS', nil, '%')
/* -*-c-*-
THIS FILE WAS AUTOGENERATED BY tool/compile_prelude.rb. DO NOT EDIT.
- soruces: <%= preludes.join(', ') %>
+ soruces: <%= @preludes.map {|n,*| prelude_base(n)}.join(', ') %>
*/
#include "ruby/ruby.h"
#include "vm_core.h"
-% preludes.zip(lines_list).each_with_index {|(prelude, (setup_lines, lines)), i|
-static const char prelude_name<%=i%>[] = <%=c_esc(prelude_name(prelude))%>;
+% preludes = @preludes.values.sort
+% preludes.each {|i, prelude, lines, sub|
+
+static const char prelude_name<%=i%>[] = <%=c_esc(prelude_name(*prelude))%>;
static const char prelude_code<%=i%>[] =
-% (setup_lines+lines).each {|line|
+% lines.each {|line|
<%=line%>
% }
;
% }
+#define PRELUDE_COUNT <%=@have_sublib ? preludes.size : 0%>
+
+% if @have_sublib or @need_ruby_prefix
+struct prelude_env {
+ volatile VALUE prefix_path;
+#if PRELUDE_COUNT > 0
+ char loaded[PRELUDE_COUNT];
+#endif
+};
+
+static VALUE
+prelude_prefix_path(VALUE self)
+{
+ struct prelude_env *ptr = DATA_PTR(self);
+ return ptr->prefix_path;
+}
+% end
+
+% if @have_sublib
+static VALUE
+prelude_require(VALUE self, VALUE nth)
+{
+ struct prelude_env *ptr = DATA_PTR(self);
+ VALUE code, name;
+ int n = FIX2INT(nth);
+
+ if (n > PRELUDE_COUNT) return Qfalse;
+ if (ptr->loaded[n]) return Qfalse;
+ ptr->loaded[n] = 1;
+ switch (n) {
+% @preludes.each_value do |i, prelude, lines, sub|
+% if sub
+ case <%=i%>:
+ code = rb_usascii_str_new(prelude_code<%=i%>, sizeof(prelude_code<%=i%>) - 1);
+ name = rb_usascii_str_new(prelude_name<%=i%>, sizeof(prelude_name<%=i%>) - 1);
+ break;
+% end
+% end
+ default:
+ return Qfalse;
+ }
+ rb_iseq_eval(rb_iseq_compile(code, name, INT2FIX(1)));
+ return Qtrue;
+}
+
+% end
void
Init_<%=init_name%>(void)
{
-% lines_list.each_with_index {|(setup_lines, lines), i|
- rb_iseq_eval(rb_iseq_compile(
- rb_usascii_str_new(prelude_code<%=i%>, sizeof(prelude_code<%=i%>) - 1),
- rb_usascii_str_new(prelude_name<%=i%>, sizeof(prelude_name<%=i%>) - 1),
- INT2FIX(<%=1-setup_lines.length%>)));
+% if @have_sublib or @need_ruby_prefix
+ struct prelude_env memo;
+ ID name = rb_intern("TMP_RUBY_PREFIX");
+ VALUE prelude = Data_Wrap_Struct(rb_cData, 0, 0, &memo);
+
+ memo.prefix_path = rb_const_remove(rb_cObject, name);
+ rb_const_set(rb_cObject, name, prelude);
+ rb_define_singleton_method(prelude, "to_s", prelude_prefix_path, 0);
+% end
+% if @have_sublib
+ memset(memo.loaded, 0, sizeof(memo.loaded));
+ rb_define_singleton_method(prelude, "require", prelude_require, 1);
+% end
+% preludes.each do |i, prelude, lines, sub|
+% next if sub
+ rb_iseq_eval(rb_iseq_compile(
+ rb_usascii_str_new(prelude_code<%=i%>, sizeof(prelude_code<%=i%>) - 1),
+ rb_usascii_str_new(prelude_name<%=i%>, sizeof(prelude_name<%=i%>) - 1),
+ INT2FIX(1)));
+% end
+% if @have_sublib or @need_ruby_prefix
+ rb_gc_force_recycle(prelude);
+% end
-% }
#if 0
% preludes.length.times {|i|
puts(prelude_code<%=i%>);
@@ -113,8 +175,14 @@ Init_<%=init_name%>(void)
#endif
}
EOS
+ tmp = erb.result(binding)
+ open(outfile, 'w'){|f|
+ f << tmp
+ }
+ end
+end
-open(outfile, 'w'){|f|
- f << tmp
-}
+preludes = ARGV.dup
+outfile = preludes.pop
+Prelude.new(preludes).emit(outfile)
diff --git a/variable.c b/variable.c
index 62256a049e..d7b99f180b 100644
--- a/variable.c
+++ b/variable.c
@@ -1633,12 +1633,19 @@ VALUE
rb_mod_remove_const(VALUE mod, VALUE name)
{
const ID id = rb_to_id(name);
- VALUE val;
- st_data_t v, n = id;
if (!rb_is_const_id(id)) {
rb_name_error(id, "`%s' is not allowed as a constant name", rb_id2name(id));
}
+ return rb_const_remove(mod, id);
+}
+
+VALUE
+rb_const_remove(VALUE mod, ID id)
+{
+ VALUE val;
+ st_data_t v, n = id;
+
if (!OBJ_UNTRUSTED(mod) && rb_safe_level() >= 4)
rb_raise(rb_eSecurityError, "Insecure: can't remove constant");
if (OBJ_FROZEN(mod)) rb_error_frozen("class/module");