aboutsummaryrefslogtreecommitdiffstats
path: root/template
diff options
context:
space:
mode:
authorNobuyoshi Nakada <nobu@ruby-lang.org>2019-11-09 19:28:45 +0900
committerNobuyoshi Nakada <nobu@ruby-lang.org>2019-11-09 19:28:45 +0900
commitdfaac2b37253ff25ec873c2fbd93abfa7f789248 (patch)
tree6517f137f767bba6811e711462d05c7dc3141c96 /template
parent4dc4b1890499d6a836655957e78908ee891a42ce (diff)
downloadruby-dfaac2b37253ff25ec873c2fbd93abfa7f789248.tar.gz
Embed builtin ruby scripts in miniprelude.c
Instead of reading from the files by the full-path at runtime. As rbinc files need to be included in distributed tarballs, the full-paths at the packaging are unavailable at compilation times.
Diffstat (limited to 'template')
-rw-r--r--template/prelude.c.tmpl61
1 files changed, 51 insertions, 10 deletions
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");