HEX
Server: Apache
System: Linux s198.coreserver.jp 5.15.0-151-generic #161-Ubuntu SMP Tue Jul 22 14:25:40 UTC 2025 x86_64
User: nagasaki (10062)
PHP: 7.1.33
Disabled: NONE
Upload Files
File: //usr/local/rvm/src/ruby-3.0.2/template/prelude.c.tmpl
<%
# 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
    @have_sublib = false
    @vpath = vpath
    @prelude_count = 0
    @builtin_count = 0
    @preludes = {}
    @mains = preludes.map do |filename|
      if prelude = filename.end_with?("golf_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

  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|
      line.force_encoding("ASCII-8BIT") if line.respond_to?(:force_encoding)
      @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, 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/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

% 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_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)
#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; */
	FALSE,/* 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 = prelude_ast(name, code, line);
    rb_iseq_eval(rb_iseq_new_with_opt(&ast->body, name, name, Qnil, INT2FIX(line),
				      NULL, 0, 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 == true
      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
% init_name = @output && @output[/\w+(?=_prelude.c\b)/] || 'prelude'
void
Init_<%=init_name%><%=%>(void)
{
%unless @prelude_count.zero?
% 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 -%>