зеркало из https://github.com/github/ruby.git
170 строки
4.6 KiB
Cheetah
170 строки
4.6 KiB
Cheetah
<%
|
|
# 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.
|
|
|
|
require_relative '../tool/ruby_vm/helpers/c_escape'
|
|
|
|
class Prelude
|
|
include RubyVM::CEscape
|
|
LINE_LIMIT = 509 # by C89
|
|
|
|
def prelude_base(filename)
|
|
filename.chomp(".rb")
|
|
end
|
|
def prelude_name(filename)
|
|
"<internal:" + prelude_base(filename) + ">"
|
|
end
|
|
|
|
def initialize(output, preludes, vpath)
|
|
@output = output
|
|
@vpath = vpath
|
|
@builtin_count = 0
|
|
@preludes = {}
|
|
@mains = preludes.map do |filename|
|
|
@builtin_count += 1
|
|
translate(filename, filename)[0]
|
|
end
|
|
@preludes.delete_if {|_, (_, _, lines, sub)| sub && lines.empty?}
|
|
end
|
|
|
|
def translate(filename, sub = false)
|
|
idx = @preludes[filename]
|
|
return idx if idx
|
|
lines = []
|
|
start_line = nil
|
|
lineno = 0
|
|
result = [@preludes.size, @vpath.strip(filename), lines, sub]
|
|
@vpath.foreach(filename) do |line|
|
|
if line.respond_to?(:force_encoding)
|
|
enc = line.encoding
|
|
line.force_encoding("ASCII-8BIT")
|
|
end
|
|
line.rstrip!
|
|
lineno += 1
|
|
@preludes[filename] ||= result
|
|
comment = ($1 || '' if line.sub!(/(?:^|\s+)\#(?!\{)(?:$|(?:[#\s]|(?=\W))(.*))/, ''))
|
|
if !line.empty? or start_line
|
|
line << "\n"
|
|
start_line ||= lineno
|
|
end
|
|
if line.size > LINE_LIMIT
|
|
raise "#{filename}:#{lines.size+1}: too long line"
|
|
end
|
|
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
|
|
# This library will be loaded before this,
|
|
# the order cannot be preserved
|
|
comment = "#{orig} #{comment}".rstrip
|
|
""
|
|
else
|
|
orig
|
|
end
|
|
end
|
|
comment.force_encoding(enc) if enc and comment
|
|
lines << [line, comment]
|
|
end
|
|
result << (start_line || 1)
|
|
result
|
|
end
|
|
end
|
|
Prelude.new(output, 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 "internal.h"
|
|
#include "internal/ruby_parser.h"
|
|
#include "internal/warnings.h"
|
|
#include "iseq.h"
|
|
#include "ruby/ruby.h"
|
|
#include "vm_core.h"
|
|
|
|
COMPILER_WARNING_PUSH
|
|
#if __has_warning("-Wstring-concatenation")
|
|
COMPILER_WARNING_IGNORED(-Wstring-concatenation)
|
|
#endif
|
|
% preludes = @preludes.values.sort
|
|
% preludes.each {|i, prelude, lines, sub|
|
|
|
|
% name = prelude_name(*prelude)
|
|
static const char prelude_name<%=i%><%=%>[] = <%=rstring2cstr(name)%>;
|
|
static const struct {
|
|
% size = beg = 0
|
|
% lines.each_with_index {|(line, comment), n|
|
|
% if size + line.size < Prelude::LINE_LIMIT
|
|
% size += line.size
|
|
% next
|
|
% end
|
|
char L<%=beg%><%=%>[<%=size%><%=%>]; /* <%=beg+1%>..<%=n%> */
|
|
% size = line.size
|
|
% beg = n
|
|
% }
|
|
% if size > 0
|
|
char L<%=beg%><%=%>[<%=size%><%=%>]; /* <%=beg+1%>..<%=lines.size+1%> */
|
|
% end
|
|
} prelude_code<%=i%><%=%> = {
|
|
% size = 0
|
|
#line 1 <%=rstring2cstr(prelude)%>
|
|
% lines.each_with_index {|(line, comment), n|
|
|
% if size + line.size >= Prelude::LINE_LIMIT
|
|
% size = 0
|
|
,
|
|
#line <%=n+1%> <%=rstring2cstr(prelude)%>
|
|
% end
|
|
% size += line.size
|
|
<%=rstring2cstr(line)%><%if comment%><%=commentify(comment)%><%end%>
|
|
% }
|
|
#line <%=_erbout.count("\n")+2%> "<%=@output%>"
|
|
};
|
|
% }
|
|
|
|
COMPILER_WARNING_POP
|
|
|
|
#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))
|
|
|
|
% end
|
|
% if @builtin_count > 0
|
|
#define PRELUDE_MATCH(n) \
|
|
(((sizeof(prelude_name<%='##'%><%=%>n) - prefix_len - 2) == namelen) && \
|
|
(strncmp(prelude_name<%='##'%><%=%>n + prefix_len, feature_name, namelen) == 0))
|
|
|
|
VALUE
|
|
rb_builtin_find(const char *feature_name, VALUE *name_str, int *start_line)
|
|
{
|
|
const size_t prefix_len = rb_strlen_lit("<internal:");
|
|
size_t namelen = strlen(feature_name);
|
|
|
|
#define PRELUDE_FOUND(n, l) \
|
|
(*name_str = PRELUDE_NAME(n), *start_line = (l), PRELUDE_CODE(n))
|
|
|
|
% @preludes.each_value do |i, prelude, lines, sub, start_line|
|
|
% if sub
|
|
if (PRELUDE_MATCH(<%=i%>)) return PRELUDE_FOUND(<%=i%>, <%=start_line%>);
|
|
% end
|
|
% end
|
|
#undef PRELUDE_FOUND
|
|
|
|
return Qnil;
|
|
}
|
|
|
|
%end
|
|
% init_name = @output && @output[/\w+(?=_prelude.c\b)/] || 'prelude'
|
|
void
|
|
Init_<%=init_name%><%=%>(void)
|
|
{
|
|
}
|
|
<%end -%>
|