diff options
author | Jari Vetoniemi <jari.vetoniemi@indooratlas.com> | 2020-03-16 18:49:26 +0900 |
---|---|---|
committer | Jari Vetoniemi <jari.vetoniemi@indooratlas.com> | 2020-03-30 00:39:06 +0900 |
commit | fcbf63e62c627deae76c1b8cb8c0876c536ed811 (patch) | |
tree | 64cb17de3f41a2b6fef2368028fbd00349946994 /jni/ruby/template/prelude.c.tmpl |
Fresh start
Diffstat (limited to 'jni/ruby/template/prelude.c.tmpl')
-rw-r--r-- | jni/ruby/template/prelude.c.tmpl | 178 |
1 files changed, 178 insertions, 0 deletions
diff --git a/jni/ruby/template/prelude.c.tmpl b/jni/ruby/template/prelude.c.tmpl new file mode 100644 index 0000000..8f331d9 --- /dev/null +++ b/jni/ruby/template/prelude.c.tmpl @@ -0,0 +1,178 @@ +<% +# This file is interpreted by $(BASERUBY) and miniruby. +# $(BASERUBY) is used for miniprelude.c. +# miniruby is used for prelude.c. +# Since $(BASERUBY) may be older than Ruby 1.9, +# Ruby 1.9 feature should not be used. + +class 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_base(filename) + filename.chomp(".rb") + end + def prelude_name(filename) + "<internal:" + prelude_base(filename) + ">" + end + + def initialize(init_name, preludes, vpath) + @init_name = init_name + @have_sublib = false + @vpath = vpath + @preludes = {} + @mains = preludes.map {|filename| translate(filename)[0]} + @preludes.delete_if {|_, (_, _, lines, sub)| sub && lines.empty?} + end + + def translate(filename, sub = false) + idx = @preludes[filename] + return idx if idx + lines = [] + result = [@preludes.size, @vpath.strip(filename), lines, sub] + @vpath.foreach(filename) do |line| + @preludes[filename] ||= result + line.sub!(/(?:^|\s+)\#(?:$|[#\s].*)/, '') + line.sub!(/require(_relative)?\s*\(?\s*(["'])(.*?)(?:\.rb)?\2\)?/) do + orig, rel, path = $&, $2, $3 + if rel + path = File.join(File.dirname(filename), path) + nil while path.gsub!(%r'(\A|/)(?!\.\.?/)[^/]+/\.\.(?:/|\z)', '') + end + path = translate("#{path}.rb", true) rescue nil + if path + @have_sublib = true + "TMP_RUBY_PREFIX.require(#{path[0]})" + else + orig + end + end + lines << c_esc(line) + end + result + end +end +Prelude.new(output && output[/\w+(?=_prelude.c\b)/] || 'prelude', ARGV, vpath).instance_eval do +-%> +/* -*-c-*- + THIS FILE WAS AUTOGENERATED BY template/prelude.c.tmpl. DO NOT EDIT. + + sources: <%= @preludes.map {|n,*| prelude_base(n)}.join(', ') %> +*/ +%unless @preludes.empty? +#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%> +% } +; +% } + +% if @have_sublib +#define PRELUDE_COUNT <%=preludes.size%> + +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 +%end +void +Init_<%=@init_name%>(void) +{ +%unless @preludes.empty? +% if @have_sublib + 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 + rb_gc_force_recycle(prelude); +% end + +#if 0 +% preludes.length.times {|i| + puts(prelude_code<%=i%>); +% } +#endif +%end +} +<%end -%> |