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/