[前][次][番号順一覧][スレッド一覧]

ruby-changes:15006

From: nobu <ko1@a...>
Date: Fri, 12 Mar 2010 07:16:56 +0900 (JST)
Subject: [ruby-changes:15006] Ruby:r26881 (trunk): * ruby.c (ruby_init_loadpath_safe, ruby_init_gems): set and remove

nobu	2010-03-12 07:15:11 +0900 (Fri, 12 Mar 2010)

  New Revision: 26881

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=26881

  Log:
    * 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.

  Modified files:
    trunk/ChangeLog
    trunk/include/ruby/intern.h
    trunk/ruby.c
    trunk/tool/compile_prelude.rb
    trunk/variable.c

Index: include/ruby/intern.h
===================================================================
--- include/ruby/intern.h	(revision 26880)
+++ include/ruby/intern.h	(revision 26881)
@@ -817,6 +817,7 @@
 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);
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 26880)
+++ ChangeLog	(revision 26881)
@@ -1,3 +1,12 @@
+Fri Mar 12 07:15:08 2010  Nobuyoshi Nakada  <nobu@r...>
+
+	* 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@r...>
 
 	* Makefile.in (config.status): setup MINIRUBY environment for
Index: variable.c
===================================================================
--- variable.c	(revision 26880)
+++ variable.c	(revision 26881)
@@ -1633,12 +1633,19 @@
 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");
Index: ruby.c
===================================================================
--- ruby.c	(revision 26880)
+++ ruby.c	(revision 26881)
@@ -358,7 +358,7 @@
 
 #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 @@
 	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 @@
 	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 @@
 #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 @@
 	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 @@
 {
     if (enable) rb_define_module("Gem");
     Init_prelude();
+    rb_const_remove(rb_cObject, rb_intern_const("TMP_RUBY_PREFIX"));
 }
 
 static int
Index: tool/compile_prelude.rb
===================================================================
--- tool/compile_prelude.rb	(revision 26880)
+++ tool/compile_prelude.rb	(revision 26881)
@@ -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
-        lines << c_esc(", TOPLEVEL_BINDING, %s, %d)" % [ prelude_name(filename, path).dump, 1])
-      else
-        lines << c_esc(orig)
+        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
       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 @@
 #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)
 

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]