aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--common.mk2
-rw-r--r--mini_builtin.c42
-rw-r--r--template/prelude.c.tmpl61
3 files changed, 56 insertions, 49 deletions
diff --git a/common.mk b/common.mk
index 56eba97f92..6996ae56c5 100644
--- a/common.mk
+++ b/common.mk
@@ -1072,7 +1072,7 @@ vm_call_iseq_optimized.inc: $(srcdir)/tool/mk_call_iseq_optimized.rb
$(MINIPRELUDE_C): $(COMPILE_PRELUDE)
$(ECHO) generating $@
$(Q) $(BASERUBY) $(srcdir)/tool/generic_erb.rb -I$(srcdir) -o $@ \
- $(srcdir)/template/prelude.c.tmpl
+ $(srcdir)/template/prelude.c.tmpl $(BUILTIN_RB_SRCS)
$(PRELUDE_C): $(COMPILE_PRELUDE) \
$(PRELUDE_SCRIPTS)
diff --git a/mini_builtin.c b/mini_builtin.c
index dc95919da2..290a4b335e 100644
--- a/mini_builtin.c
+++ b/mini_builtin.c
@@ -5,55 +5,21 @@
// include from miniinits.c
-static const char *
-read_file(const char *fname, size_t *psize)
-{
- struct stat st;
- char *code;
- FILE *fp;
-
- if (stat(fname, &st) != 0) {
- rb_bug("stat fails: %s", fname);
- }
-
- size_t fsize = st.st_size;
- if ((code = malloc(fsize + 1)) == NULL) {
- rb_bug("can't allocate memory: %s (%d)", fname, (int)fsize);
- }
-
- if ((fp = fopen(fname, "rb")) == NULL) {
- rb_bug("can't open file: %s", fname);
- }
-
- size_t read_size = fread(code, 1, fsize, fp);
- if (read_size != fsize) {
- rb_bug("can't read file enough: %s (expect %d but was %d)", fname, (int)fsize, (int)read_size);
- }
-
- code[fsize] = 0;
- *psize = fsize;
- return code;
-}
-
static struct st_table *loaded_builtin_table;
+rb_ast_t *rb_builtin_ast(const char *feature_name, VALUE *name_str);
+
void
rb_load_with_builtin_functions(const char *feature_name, const char *fname, const struct rb_builtin_function *table)
{
- size_t fsize;
- const char *code = read_file(fname, &fsize);
- VALUE code_str = rb_utf8_str_new_static(code, fsize);
- VALUE name_str = rb_sprintf("<internal:%s>", feature_name);
- rb_obj_hide(code_str);
-
- rb_ast_t *ast = rb_parser_compile_string_path(rb_parser_new(), name_str, code_str, 1);
+ VALUE name_str = 0;
+ rb_ast_t *ast = rb_builtin_ast(feature_name, &name_str);
GET_VM()->builtin_function_table = table;
const rb_iseq_t *iseq = rb_iseq_new(&ast->body, name_str, name_str, Qnil, NULL, ISEQ_TYPE_TOP);
GET_VM()->builtin_function_table = NULL;
rb_ast_dispose(ast);
- free((void *)code); // code_str becomes broken.
// register (loaded iseq will not be freed)
st_insert(loaded_builtin_table, (st_data_t)feature_name, (st_data_t)iseq);
diff --git a/template/prelude.c.tmpl b/template/prelude.c.tmpl
index 4b3a38e3b1..33f6a68be0 100644
--- a/template/prelude.c.tmpl
+++ b/template/prelude.c.tmpl
@@ -34,8 +34,17 @@ class Prelude
@output = output
@have_sublib = false
@vpath = vpath
+ @prelude_count = 0
+ @builtin_count = 0
@preludes = {}
- @mains = preludes.map {|filename| translate(filename)[0]}
+ @mains = preludes.map do |filename|
+ if prelude = filename.end_with?("prelude.rb")
+ @prelude_count += 1
+ else
+ @builtin_count += 1
+ end
+ translate(filename, (filename unless prelude))[0]
+ end
@preludes.delete_if {|_, (_, _, lines, sub)| sub && lines.empty?}
end
@@ -134,11 +143,47 @@ prelude_prefix_path(VALUE self)
struct prelude_env *ptr = DATA_PTR(self);
return ptr->prefix_path;
}
-% end
+% end
% unless preludes.empty?
#define PRELUDE_NAME(n) rb_usascii_str_new_static(prelude_name##n, sizeof(prelude_name##n)-1)
#define PRELUDE_CODE(n) rb_utf8_str_new_static(prelude_code##n.L0, sizeof(prelude_code##n))
+
+static rb_ast_t *
+prelude_ast(VALUE name, VALUE code, int line)
+{
+ rb_ast_t *ast = rb_parser_compile_string_path(rb_parser_new(), name, code, line);
+ if (!ast->body.root) {
+ rb_ast_dispose(ast);
+ rb_exc_raise(rb_errinfo());
+ }
+ return ast;
+}
+
+% end
+% if @builtin_count > 0
+#define PRELUDE_AST(n, name_str) \
+ (((sizeof(prelude_name<%='##'%><%=%>n) - prefix_len - 2) == namelen) && \
+ (strncmp(prelude_name<%='##'%><%=%>n + prefix_len, feature_name, namelen) == 0) ? \
+ prelude_ast((name_str) = PRELUDE_NAME(n), PRELUDE_CODE(n), 1) : 0)
+
+rb_ast_t *
+rb_builtin_ast(const char *feature_name, VALUE *name_str)
+{
+ const size_t prefix_len = rb_strlen_lit("<internal:");
+ size_t namelen = strlen(feature_name);
+ rb_ast_t *ast = 0;
+
+% @preludes.each_value do |i, prelude, lines, sub|
+% if sub and sub != true
+ if ((ast = PRELUDE_AST(<%=i%><%=%>, *name_str)) != 0) return ast;
+% end
+% end
+ return ast;
+}
+
+% end
+% if @prelude_count > 0
COMPILER_WARNING_PUSH
#if GCC_VERSION_SINCE(4, 2, 0)
COMPILER_WARNING_ERROR(-Wmissing-field-initializers)
@@ -160,18 +205,14 @@ prelude_eval(VALUE code, VALUE name, int line)
0, /* int debug_level; */
};
- rb_ast_t *ast = rb_parser_compile_string_path(rb_parser_new(), name, code, line);
- if (!ast->body.root) {
- rb_ast_dispose(ast);
- rb_exc_raise(rb_errinfo());
- }
+ rb_ast_t *ast = prelude_ast(name, code, line);
rb_iseq_eval(rb_iseq_new_with_opt(&ast->body, name, name, Qnil, INT2FIX(line),
NULL, ISEQ_TYPE_TOP, &optimization));
rb_ast_dispose(ast);
}
COMPILER_WARNING_POP
-% end
+% end
% if @have_sublib
static VALUE
prelude_require(VALUE self, VALUE nth)
@@ -185,7 +226,7 @@ prelude_require(VALUE self, VALUE nth)
ptr->loaded[n] = 1;
switch (n) {
% @preludes.each_value do |i, prelude, lines, sub|
-% if sub
+% if sub == true
case <%=i%><%=%>:
code = PRELUDE_CODE(<%=i%><%=%>);
name = PRELUDE_NAME(<%=i%><%=%>);
@@ -205,7 +246,7 @@ prelude_require(VALUE self, VALUE nth)
void
Init_<%=init_name%><%=%>(void)
{
-%unless @preludes.empty?
+%unless @prelude_count.zero?
% if @have_sublib
struct prelude_env memo;
ID name = rb_intern("TMP_RUBY_PREFIX");