diff --git a/tasks/mrbgems.rake b/tasks/mrbgems.rake index ea381467f..26d736bfd 100644 --- a/tasks/mrbgems.rake +++ b/tasks/mrbgems.rake @@ -13,15 +13,14 @@ MRuby.each_target do mkdir_p "#{build_dir}/mrbgems" open(t.name, 'w') do |f| gem_func_gems = gems.select { |g| g.generate_functions } - gem_func_decls = gem_func_gems.each_with_object('') do |g, s| - s << "void GENERATED_TMP_mrb_#{g.funcname}_gem_init(mrb_state*);\n" \ - "void GENERATED_TMP_mrb_#{g.funcname}_gem_final(mrb_state*);\n" - end - gem_funcs = gem_func_gems.each_with_object('') do |g, s| - s << " { GENERATED_TMP_mrb_#{g.funcname}_gem_init },\n" - end - gem_final_calls = gem_func_gems.reverse_each.with_object('') do |g, s| - s << " GENERATED_TMP_mrb_#{g.funcname}_gem_final(mrb);\n" + gem_func_decls = '' + gem_funcs = '' + gem_func_gems.each do |g| + init = "GENERATED_TMP_mrb_#{g.funcname}_gem_init" + final = "GENERATED_TMP_mrb_#{g.funcname}_gem_final" + gem_func_decls << "void #{init}(mrb_state*);\n" \ + "void #{final}(mrb_state*);\n" + gem_funcs << " { #{init}, #{final} },\n" end f.puts %Q[/*] f.puts %Q[ * This file contains a list of all] @@ -36,24 +35,43 @@ MRuby.each_target do f.puts %Q[ */] f.puts %Q[] f.puts %Q[#include ] + f.puts %Q[#include ] f.puts %Q[#include ] f.puts %Q[] f.write gem_func_decls f.puts %Q[] f.puts %Q[static const struct {] f.puts %Q[ void (*init)(mrb_state*);] + f.puts %Q[ void (*final)(mrb_state*);] f.puts %Q[} gem_funcs[] = {] f.write gem_funcs f.puts %Q[};] f.puts %Q[] f.puts %Q[#define NUM_GEMS ((int)(sizeof(gem_funcs) / sizeof(gem_funcs[0])))] - unless gem_final_calls.empty? - f.puts %Q[] - f.puts %Q[static void] - f.puts %Q[mrb_final_mrbgems(mrb_state *mrb) {] - f.write gem_final_calls - f.puts %Q[}] - end + f.puts %Q[] + f.puts %Q[struct final_mrbgems {] + f.puts %Q[ int i;] + f.puts %Q[ int ai;] + f.puts %Q[};] + f.puts %Q[] + f.puts %Q[static mrb_value] + f.puts %Q[final_mrbgems_body(mrb_state *mrb, void *ud) {] + f.puts %Q[ struct final_mrbgems *p = (struct final_mrbgems*)ud;] + f.puts %Q[ for (; p->i >= 0; p->i--) {] + f.puts %Q[ gem_funcs[p->i].final(mrb);] + f.puts %Q[ mrb_gc_arena_restore(mrb, p->ai);] + f.puts %Q[ }] + f.puts %Q[ return mrb_nil_value();] + f.puts %Q[}] + f.puts %Q[] + f.puts %Q[static void] + f.puts %Q[mrb_final_mrbgems(mrb_state *mrb) {] + f.puts %Q[ struct final_mrbgems a = { NUM_GEMS - 1, mrb_gc_arena_save(mrb) };] + f.puts %Q[ for (; a.i >= 0; a.i--) {] + f.puts %Q[ mrb_protect_error(mrb, final_mrbgems_body, &a, NULL);] + f.puts %Q[ mrb_gc_arena_restore(mrb, a.ai);] + f.puts %Q[ }] + f.puts %Q[}] f.puts %Q[] f.puts %Q[void] f.puts %Q[mrb_init_mrbgems(mrb_state *mrb) {]