* 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
@ -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>
|
Fri Mar 12 07:09:20 2010 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||||
|
|
||||||
* Makefile.in (config.status): setup MINIRUBY environment for
|
* 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_at(VALUE, ID);
|
||||||
VALUE rb_const_get_from(VALUE, ID);
|
VALUE rb_const_get_from(VALUE, ID);
|
||||||
void rb_const_set(VALUE, ID, VALUE);
|
void rb_const_set(VALUE, ID, VALUE);
|
||||||
|
VALUE rb_const_remove(VALUE, ID);
|
||||||
VALUE rb_mod_const_missing(VALUE,VALUE);
|
VALUE rb_mod_const_missing(VALUE,VALUE);
|
||||||
VALUE rb_cvar_defined(VALUE, ID);
|
VALUE rb_cvar_defined(VALUE, ID);
|
||||||
void rb_cvar_set(VALUE, ID, VALUE);
|
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 defined _WIN32 || defined __CYGWIN__
|
||||||
# if VARIABLE_LIBPATH
|
# if VARIABLE_LIBPATH
|
||||||
sopath = rb_str_tmp_new(MAXPATHLEN);
|
sopath = rb_str_new(0, MAXPATHLEN);
|
||||||
libpath = RSTRING_PTR(sopath);
|
libpath = RSTRING_PTR(sopath);
|
||||||
GetModuleFileName(libruby, libpath, MAXPATHLEN);
|
GetModuleFileName(libruby, libpath, MAXPATHLEN);
|
||||||
# else
|
# else
|
||||||
@ -390,7 +390,7 @@ ruby_init_loadpath_safe(int safe_level)
|
|||||||
const int win_to_posix = CCP_WIN_A_TO_POSIX | CCP_RELATIVE;
|
const int win_to_posix = CCP_WIN_A_TO_POSIX | CCP_RELATIVE;
|
||||||
size_t newsize = cygwin_conv_path(win_to_posix, libpath, 0, 0);
|
size_t newsize = cygwin_conv_path(win_to_posix, libpath, 0, 0);
|
||||||
if (newsize > 0) {
|
if (newsize > 0) {
|
||||||
VALUE rubylib = rb_str_tmp_new(newsize);
|
VALUE rubylib = rb_str_new(0, newsize);
|
||||||
p = RSTRING_PTR(rubylib);
|
p = RSTRING_PTR(rubylib);
|
||||||
if (cygwin_conv_path(win_to_posix, libpath, p, newsize) == 0) {
|
if (cygwin_conv_path(win_to_posix, libpath, p, newsize) == 0) {
|
||||||
rb_str_resize(sopath, 0);
|
rb_str_resize(sopath, 0);
|
||||||
@ -418,8 +418,10 @@ ruby_init_loadpath_safe(int safe_level)
|
|||||||
strlcpy(libpath, ".", sizeof(libpath));
|
strlcpy(libpath, ".", sizeof(libpath));
|
||||||
p = libpath + 1;
|
p = libpath + 1;
|
||||||
}
|
}
|
||||||
|
#define PREFIX_PATH() rb_str_new(libpath, baselen)
|
||||||
#else
|
#else
|
||||||
rb_str_set_len(sopath, p - libpath);
|
rb_str_set_len(sopath, p - libpath);
|
||||||
|
#define PREFIX_PATH() sopath
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
baselen = p - libpath;
|
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)
|
#define RUBY_RELATIVE(path, len) rb_str_buf_cat(BASEPATH(), path, len)
|
||||||
#else
|
#else
|
||||||
#define RUBY_RELATIVE(path, len) rubylib_mangled_path(path, len)
|
#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
|
#endif
|
||||||
#define incpush(path) rb_ary_push(load_path, (path))
|
#define incpush(path) rb_ary_push(load_path, (path))
|
||||||
load_path = GET_VM()->load_path;
|
load_path = GET_VM()->load_path;
|
||||||
@ -441,6 +444,8 @@ ruby_init_loadpath_safe(int safe_level)
|
|||||||
incpush(RUBY_RELATIVE(paths, len));
|
incpush(RUBY_RELATIVE(paths, len));
|
||||||
paths += len + 1;
|
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");
|
if (enable) rb_define_module("Gem");
|
||||||
Init_prelude();
|
Init_prelude();
|
||||||
|
rb_const_remove(rb_cObject, rb_intern_const("TMP_RUBY_PREFIX"));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -4,108 +4,170 @@
|
|||||||
# Since $(BASERUBY) may be older than Ruby 1.9,
|
# Since $(BASERUBY) may be older than Ruby 1.9,
|
||||||
# Ruby 1.9 feature should not be used.
|
# 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'
|
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-*-
|
/* -*-c-*-
|
||||||
THIS FILE WAS AUTOGENERATED BY tool/compile_prelude.rb. DO NOT EDIT.
|
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 "ruby/ruby.h"
|
||||||
#include "vm_core.h"
|
#include "vm_core.h"
|
||||||
|
|
||||||
% preludes.zip(lines_list).each_with_index {|(prelude, (setup_lines, lines)), i|
|
% preludes = @preludes.values.sort
|
||||||
static const char prelude_name<%=i%>[] = <%=c_esc(prelude_name(prelude))%>;
|
% preludes.each {|i, prelude, lines, sub|
|
||||||
|
|
||||||
|
static const char prelude_name<%=i%>[] = <%=c_esc(prelude_name(*prelude))%>;
|
||||||
static const char prelude_code<%=i%>[] =
|
static const char prelude_code<%=i%>[] =
|
||||||
% (setup_lines+lines).each {|line|
|
% lines.each {|line|
|
||||||
<%=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
|
void
|
||||||
Init_<%=init_name%>(void)
|
Init_<%=init_name%>(void)
|
||||||
{
|
{
|
||||||
% lines_list.each_with_index {|(setup_lines, lines), i|
|
% if @have_sublib or @need_ruby_prefix
|
||||||
rb_iseq_eval(rb_iseq_compile(
|
struct prelude_env memo;
|
||||||
rb_usascii_str_new(prelude_code<%=i%>, sizeof(prelude_code<%=i%>) - 1),
|
ID name = rb_intern("TMP_RUBY_PREFIX");
|
||||||
rb_usascii_str_new(prelude_name<%=i%>, sizeof(prelude_name<%=i%>) - 1),
|
VALUE prelude = Data_Wrap_Struct(rb_cData, 0, 0, &memo);
|
||||||
INT2FIX(<%=1-setup_lines.length%>)));
|
|
||||||
|
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
|
#if 0
|
||||||
% preludes.length.times {|i|
|
% preludes.length.times {|i|
|
||||||
puts(prelude_code<%=i%>);
|
puts(prelude_code<%=i%>);
|
||||||
@ -113,8 +175,14 @@ Init_<%=init_name%>(void)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
EOS
|
EOS
|
||||||
|
tmp = erb.result(binding)
|
||||||
|
open(outfile, 'w'){|f|
|
||||||
|
f << tmp
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
open(outfile, 'w'){|f|
|
preludes = ARGV.dup
|
||||||
f << tmp
|
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)
|
rb_mod_remove_const(VALUE mod, VALUE name)
|
||||||
{
|
{
|
||||||
const ID id = rb_to_id(name);
|
const ID id = rb_to_id(name);
|
||||||
VALUE val;
|
|
||||||
st_data_t v, n = id;
|
|
||||||
|
|
||||||
if (!rb_is_const_id(id)) {
|
if (!rb_is_const_id(id)) {
|
||||||
rb_name_error(id, "`%s' is not allowed as a constant name", rb_id2name(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)
|
if (!OBJ_UNTRUSTED(mod) && rb_safe_level() >= 4)
|
||||||
rb_raise(rb_eSecurityError, "Insecure: can't remove constant");
|
rb_raise(rb_eSecurityError, "Insecure: can't remove constant");
|
||||||
if (OBJ_FROZEN(mod)) rb_error_frozen("class/module");
|
if (OBJ_FROZEN(mod)) rb_error_frozen("class/module");
|
||||||
|
Loading…
x
Reference in New Issue
Block a user