summaryrefslogtreecommitdiff
path: root/tool/compile_prelude.rb
diff options
context:
space:
mode:
authornobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2010-03-11 22:15:11 +0000
committernobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2010-03-11 22:15:11 +0000
commit1dcf1174ea2a803e6905a04760121fe1426035b3 (patch)
tree3f37ee14e1b8c7b5f6f9ce6e1e978bbf1d12d177 /tool/compile_prelude.rb
parent9a5b57f61fd9ef14b1bc6c0b540c0edbb86a409a (diff)
* 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
Diffstat (limited to 'tool/compile_prelude.rb')
-rwxr-xr-xtool/compile_prelude.rb222
1 files changed, 145 insertions, 77 deletions
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)