Methods
C
E
N
P
T
Constants
SRCDIR = File.dirname(File.dirname(__FILE__))
 
C_ESC = { "\\" => "\\\\", '"' => '\"', "\n" => '\n', }
 
C_ESC_PAT = Regexp.union(*C_ESC.keys)
 
Class Public methods
new(preludes)
# File tool/compile_prelude.rb, line 33
def initialize(preludes)
  @mkconf = nil
  @have_sublib = false
  @need_ruby_prefix = false
  @preludes = {}
  @mains = preludes.map {|filename| translate(filename)[0]}
  @preludes.delete_if {|_, (_, _, lines, sub)| !sub && lines.empty?}
end
Instance Public methods
c_esc(str)
# File tool/compile_prelude.rb, line 23
def c_esc(str)
  '"' + str.gsub(C_ESC_PAT) { C_ESC[$&] } + '"'
end
emit(outfile)
# File tool/compile_prelude.rb, line 77
  def emit(outfile)
    @init_name = outfile[/\w+(?=_prelude.c\b)/] || 'prelude'
    erb = ERB.new("/* -*-c-*-
 THIS FILE WAS AUTOGENERATED BY tool/compile_prelude.rb. DO NOT EDIT.

 sources: <%= @preludes.map {|n,*| prelude_base(n)}.join(', ') %>
*/
#include "ruby/ruby.h"
#include "internal.h"
#include "vm_core.h"

% 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%>[] =
%   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

% unless preludes.empty?
static void
prelude_eval(VALUE code, VALUE name, VALUE line)
{
    rb_iseq_eval(rb_iseq_compile_with_option(code, name, Qnil, line, 0, Qtrue));
}
% 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;
    }
    prelude_eval(code, name, INT2FIX(1));
    return Qtrue;
}

% end
void
Init_<%=@init_name%>(void)
{
% 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
    prelude_eval(
      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%>);
% }
#endif
}
", nil, '%')
    tmp = erb.result(binding)
    open(outfile, 'w'){|f|
      f << tmp
    }
  end
prelude_base(filename)
# File tool/compile_prelude.rb, line 26
def prelude_base(filename)
  filename[/\A#{Regexp.quote(SRCDIR)}\/(.*?)(\.rb)?\z/om, 1]
end
prelude_name(filename)
# File tool/compile_prelude.rb, line 29
def prelude_name(filename)
  "<internal:" + prelude_base(filename) + ">"
end
translate(filename, sub = false)
# File tool/compile_prelude.rb, line 42
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