mirror of
				https://github.com/ruby/ruby.git
				synced 2022-11-09 12:17:21 -05:00 
			
		
		
		
	We see several occurrence of "diagnostic push/pop" so why not make them macros. Tested on GCC8 / Clang 6. Note that ruby.h is intentionally left untouched because we don't want to introduce new public macros. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@64118 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
		
			
				
	
	
		
			235 lines
		
	
	
	
		
			6.2 KiB
		
	
	
	
		
			Cheetah
		
	
	
	
	
	
			
		
		
	
	
			235 lines
		
	
	
	
		
			6.2 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.
 | 
						|
 | 
						|
class Prelude
 | 
						|
  LINE_LIMIT = 509 # by C89
 | 
						|
 | 
						|
  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
 | 
						|
      comment = ($1 || '' if line.sub!(/(?:^|\s+)\#(?:$|[#\s](.*))/, ''))
 | 
						|
      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
 | 
						|
          @have_sublib = true
 | 
						|
          "TMP_RUBY_PREFIX.require(#{path[0]})"
 | 
						|
        else
 | 
						|
          orig
 | 
						|
        end
 | 
						|
      end
 | 
						|
      lines << [line, comment]
 | 
						|
    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"
 | 
						|
#include "iseq.h"
 | 
						|
 | 
						|
% preludes = @preludes.values.sort
 | 
						|
% preludes.each {|i, prelude, lines, sub|
 | 
						|
 | 
						|
%   name = prelude_name(*prelude)
 | 
						|
static const char prelude_name<%=i%><%=%>[] = "<%=c_esc(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 "<%=c_esc(prelude)%>"
 | 
						|
%   lines.each_with_index {|(line, comment), n|
 | 
						|
%     if size + line.size >= Prelude::LINE_LIMIT
 | 
						|
%       size = 0
 | 
						|
,
 | 
						|
#line <%=n+1%> "<%=c_esc(prelude)%>"
 | 
						|
%     end
 | 
						|
%     size += line.size
 | 
						|
"<%=c_esc(line)%>"<%if comment%>/* <%=c_esc(comment)%> */<%end%>
 | 
						|
%   }
 | 
						|
#line <%=_erbout.count("\n")+2%> "<%=@init_name%>.c"
 | 
						|
};
 | 
						|
% }
 | 
						|
 | 
						|
% 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?
 | 
						|
#define PRELUDE_NAME(n) rb_usascii_str_new_static(prelude_name##n, sizeof(prelude_name##n)-1)
 | 
						|
#define PRELUDE_CODE(n) rb_usascii_str_new_static(prelude_code##n.L0, sizeof(prelude_code##n))
 | 
						|
COMPILER_WARNING_PUSH
 | 
						|
#if GCC_VERSION_SINCE(4, 2, 0)
 | 
						|
COMPILER_WARNING_ERROR(-Wmissing-field-initializers)
 | 
						|
#endif
 | 
						|
static void
 | 
						|
prelude_eval(VALUE code, VALUE name, int line)
 | 
						|
{
 | 
						|
    static const rb_compile_option_t optimization = {
 | 
						|
	TRUE, /* int inline_const_cache; */
 | 
						|
	TRUE, /* int peephole_optimization; */
 | 
						|
	TRUE, /* int tailcall_optimization; */
 | 
						|
	TRUE, /* int specialized_instruction; */
 | 
						|
	TRUE, /* int operands_unification; */
 | 
						|
	TRUE, /* int instructions_unification; */
 | 
						|
	TRUE, /* int stack_caching; */
 | 
						|
	TRUE, /* int frozen_string_literal; */
 | 
						|
	FALSE, /* int debug_frozen_string_literal; */
 | 
						|
	FALSE, /* unsigned int coverage_enabled; */
 | 
						|
	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_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
 | 
						|
 | 
						|
% 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 = PRELUDE_CODE(<%=i%><%=%>);
 | 
						|
	name = PRELUDE_NAME(<%=i%><%=%>);
 | 
						|
	break;
 | 
						|
%     end
 | 
						|
%   end
 | 
						|
      default:
 | 
						|
	return Qfalse;
 | 
						|
    }
 | 
						|
    prelude_eval(code, name, 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(PRELUDE_CODE(<%=i%><%=%>), PRELUDE_NAME(<%=i%><%=%>), 1);
 | 
						|
% end
 | 
						|
% if @have_sublib
 | 
						|
    rb_gc_force_recycle(prelude);
 | 
						|
% end
 | 
						|
 | 
						|
#if 0
 | 
						|
% preludes.length.times {|i|
 | 
						|
    printf("%.*s", (int)sizeof(prelude_code<%=i%><%=%>), prelude_code<%=i%><%=%>.L0);
 | 
						|
% }
 | 
						|
#endif
 | 
						|
%end
 | 
						|
}
 | 
						|
<%end -%>
 |