2007-11-10 11:33:30 -05:00
|
|
|
# This file is interpreted by $(BASERUBY) and miniruby.
|
2007-11-14 21:54:55 -05:00
|
|
|
# $(BASERUBY) is used for miniprelude.c.
|
|
|
|
# miniruby is used for prelude.c.
|
2007-11-10 11:33:30 -05:00
|
|
|
# Since $(BASERUBY) may be older than Ruby 1.9,
|
|
|
|
# Ruby 1.9 feature should not be used.
|
|
|
|
|
2010-03-11 17:15:11 -05:00
|
|
|
require 'erb'
|
2007-12-17 07:41:27 -05:00
|
|
|
|
2010-03-11 17:15:11 -05:00
|
|
|
class Prelude
|
|
|
|
SRCDIR = File.dirname(File.dirname(__FILE__))
|
|
|
|
$:.unshift(SRCDIR)
|
2007-08-24 11:26:28 -04:00
|
|
|
|
2010-03-11 17:15:11 -05:00
|
|
|
C_ESC = {
|
|
|
|
"\\" => "\\\\",
|
|
|
|
'"' => '\"',
|
|
|
|
"\n" => '\n',
|
|
|
|
}
|
2007-11-10 04:22:59 -05:00
|
|
|
|
2010-03-11 17:15:11 -05:00
|
|
|
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)
|
2007-11-10 04:22:59 -05:00
|
|
|
|
2010-03-11 17:15:11 -05:00
|
|
|
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
|
2007-08-24 11:26:28 -04:00
|
|
|
|
2010-03-11 17:15:11 -05:00
|
|
|
def initialize(preludes)
|
|
|
|
@mkconf = nil
|
|
|
|
@have_sublib = false
|
|
|
|
@need_ruby_prefix = false
|
|
|
|
@preludes = {}
|
|
|
|
@mains = preludes.map {|filename| translate(filename)[0]}
|
2011-01-14 20:00:09 -05:00
|
|
|
@preludes.delete_if {|_, (_, _, lines, sub)| !sub && lines.empty?}
|
2010-03-11 17:15:11 -05:00
|
|
|
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|
|
2014-07-04 01:17:04 -04:00
|
|
|
line.sub!(/(?:^|\s+)\#(?:$|\s.*)/, '')
|
2010-03-11 17:15:11 -05:00
|
|
|
line.gsub!(/RbConfig::CONFIG\["(\w+)"\]/) {
|
|
|
|
key = $1
|
|
|
|
unless @mkconf
|
|
|
|
require './rbconfig'
|
2010-03-12 10:11:10 -05:00
|
|
|
@mkconf = RbConfig::MAKEFILE_CONFIG.merge('prefix'=>'#{TMP_RUBY_PREFIX}')
|
2010-03-11 17:15:11 -05:00
|
|
|
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
|
2009-07-31 02:09:13 -04:00
|
|
|
end
|
2009-07-30 10:12:25 -04:00
|
|
|
end
|
2009-07-31 02:09:13 -04:00
|
|
|
lines << c_esc(line)
|
|
|
|
end
|
2010-03-11 17:15:11 -05:00
|
|
|
result
|
2007-11-14 21:54:55 -05:00
|
|
|
end
|
2007-08-24 11:26:28 -04:00
|
|
|
|
2010-03-11 17:15:11 -05:00
|
|
|
def emit(outfile)
|
2012-07-25 02:49:35 -04:00
|
|
|
@init_name = outfile[/\w+(?=_prelude.c\b)/] || 'prelude'
|
2010-03-11 17:15:11 -05:00
|
|
|
erb = ERB.new(<<'EOS', nil, '%')
|
2009-07-30 10:12:25 -04:00
|
|
|
/* -*-c-*-
|
|
|
|
THIS FILE WAS AUTOGENERATED BY tool/compile_prelude.rb. DO NOT EDIT.
|
|
|
|
|
2010-04-19 20:29:26 -04:00
|
|
|
sources: <%= @preludes.map {|n,*| prelude_base(n)}.join(', ') %>
|
2009-07-30 10:12:25 -04:00
|
|
|
*/
|
2007-08-24 11:26:28 -04:00
|
|
|
#include "ruby/ruby.h"
|
* internal.h: declare internal functions here.
* node.h: declare NODE dependent internal functions here.
* iseq.h: declare rb_iseq_t dependent internal functions here.
* vm_core.h: declare rb_thread_t dependent internal functions here.
* bignum.c, class.c, compile.c, complex.c, cont.c, dir.c, encoding.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c, io.c,
iseq.c, load.c, marshal.c, math.c, numeric.c, object.c, parse.y,
proc.c, process.c, range.c, rational.c, re.c, ruby.c, string.c,
thread.c, time.c, transcode.c, variable.c, vm.c,
tool/compile_prelude.rb: don't declare internal functions declared
in above headers. include above headers if required.
Note that rb_thread_mark() was declared as
void rb_thread_mark(rb_thread_t *th) in cont.c but defined as
void rb_thread_mark(void *ptr) in vm.c. Now it is declared as
the later in internal.h.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@32156 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2011-06-17 18:43:38 -04:00
|
|
|
#include "internal.h"
|
2007-08-24 19:49:19 -04:00
|
|
|
#include "vm_core.h"
|
|
|
|
|
2010-03-11 17:15:11 -05:00
|
|
|
% preludes = @preludes.values.sort
|
|
|
|
% preludes.each {|i, prelude, lines, sub|
|
|
|
|
|
|
|
|
static const char prelude_name<%=i%>[] = <%=c_esc(prelude_name(*prelude))%>;
|
2007-12-20 19:27:40 -05:00
|
|
|
static const char prelude_code<%=i%>[] =
|
2010-03-11 17:15:11 -05:00
|
|
|
% lines.each {|line|
|
2007-12-20 19:27:40 -05:00
|
|
|
<%=line%>
|
|
|
|
% }
|
2007-08-24 11:26:28 -04:00
|
|
|
;
|
2007-12-20 19:27:40 -05:00
|
|
|
% }
|
2007-08-24 21:20:30 -04:00
|
|
|
|
2010-03-11 17:15:11 -05:00
|
|
|
#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
|
|
|
|
|
2010-04-27 20:49:25 -04:00
|
|
|
% unless preludes.empty?
|
|
|
|
static void
|
|
|
|
prelude_eval(VALUE code, VALUE name, VALUE line)
|
|
|
|
{
|
* iseq.c, vm_eval.c: set th->base_block properly.
th->base_block is information for (a) parsing, (b) compiling
and (c) setting up the frame to execute the program passed by
`eval' method. For example, (1) parser need to know up-level
variables to detect it is variable or method without paren.
Befor (a), (b) and (c), VM set th->base_block by passed bindng
(or previous frame information). After execute (a), (b) and (c),
VM should clear th->base_block. However, if (a), (b) or (c)
raises an exception, then th->base_block is not cleared.
Problem is that the uncleared value th->balo_block is used for
irrelevant iseq compilation. It causes SEGV or critical error.
I tried to solve this problem: to clear them before exception,
but finally I found out that it is difficult to do it (Ruby
program can be run in many places).
Because of this background, I set th->base_block before
compiling iseq and restore it after compiling.
Basically, th->base_block is dirty hack (similar to global
variable) and this patch is also dirty.
* bootstraptest/test_eval.rb: add a test for above.
* internal.h: remove unused decl.
* iseq.c (rb_iseq_compile_with_option): add base_block parameter.
set th->base_block before compation and restore it after
compilation.
* ruby.c (require_libraries): pass 0 as base_block instead of
setting th->base_block
* tool/compile_prelude.rb (prelude_eval): apply above changes.
* vm.c, vm_eval.c: ditto.
* vm_core.h: add comments.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@36179 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2012-06-22 05:32:56 -04:00
|
|
|
rb_iseq_eval(rb_iseq_compile_with_option(code, name, Qnil, line, 0, Qtrue));
|
2010-04-27 20:49:25 -04:00
|
|
|
}
|
|
|
|
% end
|
|
|
|
|
2010-03-11 17:15:11 -05:00
|
|
|
% 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;
|
|
|
|
}
|
2010-04-27 20:49:25 -04:00
|
|
|
prelude_eval(code, name, INT2FIX(1));
|
2010-03-11 17:15:11 -05:00
|
|
|
return Qtrue;
|
|
|
|
}
|
|
|
|
|
|
|
|
% end
|
2007-08-24 11:26:28 -04:00
|
|
|
void
|
2012-07-25 02:49:35 -04:00
|
|
|
Init_<%=@init_name%>(void)
|
2007-08-24 11:26:28 -04:00
|
|
|
{
|
2010-03-11 17:15:11 -05:00
|
|
|
% 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
|
2010-04-27 20:49:25 -04:00
|
|
|
prelude_eval(
|
2010-03-11 17:15:11 -05:00
|
|
|
rb_usascii_str_new(prelude_code<%=i%>, sizeof(prelude_code<%=i%>) - 1),
|
|
|
|
rb_usascii_str_new(prelude_name<%=i%>, sizeof(prelude_name<%=i%>) - 1),
|
2010-04-27 20:49:25 -04:00
|
|
|
INT2FIX(1));
|
2010-03-11 17:15:11 -05:00
|
|
|
% end
|
|
|
|
% if @have_sublib or @need_ruby_prefix
|
|
|
|
rb_gc_force_recycle(prelude);
|
|
|
|
% end
|
2007-08-24 19:49:19 -04:00
|
|
|
|
|
|
|
#if 0
|
2007-12-20 19:27:40 -05:00
|
|
|
% preludes.length.times {|i|
|
|
|
|
puts(prelude_code<%=i%>);
|
|
|
|
% }
|
2007-08-24 19:49:19 -04:00
|
|
|
#endif
|
2007-08-24 11:26:28 -04:00
|
|
|
}
|
2007-11-14 22:26:20 -05:00
|
|
|
EOS
|
2010-03-11 17:15:11 -05:00
|
|
|
tmp = erb.result(binding)
|
|
|
|
open(outfile, 'w'){|f|
|
|
|
|
f << tmp
|
|
|
|
}
|
|
|
|
end
|
|
|
|
end
|
2007-11-14 22:26:20 -05:00
|
|
|
|
2010-03-11 17:15:11 -05:00
|
|
|
preludes = ARGV.dup
|
|
|
|
outfile = preludes.pop
|
|
|
|
Prelude.new(preludes).emit(outfile)
|
2007-08-24 11:26:28 -04:00
|
|
|
|