mirror of
				https://github.com/ruby/ruby.git
				synced 2022-11-09 12:17:21 -05:00 
			
		
		
		
	* 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. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@26881 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
		
							parent
							
								
									9a5b57f61f
								
							
						
					
					
						commit
						1dcf1174ea
					
				
					 5 changed files with 181 additions and 90 deletions
				
			
		| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										10
									
								
								ruby.c
									
										
									
									
									
								
							
							
						
						
									
										10
									
								
								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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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__))
 | 
			
		||||
 | 
			
		||||
preludes = ARGV.dup
 | 
			
		||||
outfile = preludes.pop
 | 
			
		||||
init_name = outfile[/\w+(?=_prelude.c\b)/] || 'prelude'
 | 
			
		||||
 | 
			
		||||
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)
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
 | 
			
		||||
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)
 | 
			
		||||
        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)
 | 
			
		||||
  end
 | 
			
		||||
  [setup_lines, lines]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
require 'erb'
 | 
			
		||||
 | 
			
		||||
tmp = ERB.new(<<'EOS', nil, '%').result(binding)
 | 
			
		||||
class Prelude
 | 
			
		||||
  SRCDIR = File.dirname(File.dirname(__FILE__))
 | 
			
		||||
  $:.unshift(SRCDIR)
 | 
			
		||||
 | 
			
		||||
  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)
 | 
			
		||||
 | 
			
		||||
  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
 | 
			
		||||
 | 
			
		||||
  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
 | 
			
		||||
      end
 | 
			
		||||
      lines << c_esc(line)
 | 
			
		||||
    end
 | 
			
		||||
    result
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  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)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										11
									
								
								variable.c
									
										
									
									
									
								
							
							
						
						
									
										11
									
								
								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");
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue