* prelude.rb, Makefile.in, common.mk: Introduce prelude.rb.

* eval.c (rb_eval_prelude): New function exported only for use in
  preludes.

* configure.in: Define RUBY_EXEC_PREFIX and RUBY_LIB_PREFIX.

* ruby.c (proc_options, ruby_init_loadpath, ruby_prelude): Load
  prelude.

* compile_prelude.rb: Port the prelude compiler from trunk.

* miniprelude.c: Currently miniruby does not include prelude.rb.



git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_8@27053 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
knu 2010-03-25 19:11:51 +00:00
parent 908667e45a
commit 5c54c57521
8 changed files with 247 additions and 6 deletions

View file

@ -51,7 +51,7 @@ LDSHARED = @LIBRUBY_LDSHARED@
DLDFLAGS = @LIBRUBY_DLDFLAGS@ $(EXTLDFLAGS) @ARCH_FLAG@
SOLIBS = @SOLIBS@
MAINLIBS = @MAINLIBS@
MINIOBJS = @MINIOBJS@
ARCHMINIOBJS = @MINIOBJS@
RUBY_INSTALL_NAME=@RUBY_INSTALL_NAME@
RUBY_SO_NAME=@RUBY_SO_NAME@
@ -107,7 +107,7 @@ all:
miniruby$(EXEEXT):
@$(RM) $@
$(PURIFY) $(CC) $(LDFLAGS) $(XLDFLAGS) $(MAINLIBS) $(MAINOBJ) $(MINIOBJS) $(LIBRUBY_A) $(LIBS) $(OUTFLAG)$@
$(PURIFY) $(CC) $(LDFLAGS) $(XLDFLAGS) $(MAINLIBS) $(MAINOBJ) $(MINIOBJS) $(COMMONOBJS) $(DMYEXT) $(LIBS) $(OUTFLAG)$@
$(PROGRAM):
@$(RM) $@

View file

@ -20,8 +20,9 @@ DMYEXT = dmyext.$(OBJEXT)
MAINOBJ = main.$(OBJEXT)
EXTOBJS =
DLDOBJS = $(DMYEXT)
MINIOBJS = $(ARCHMINIOBJS) miniprelude.$(OBJEXT)
OBJS = array.$(OBJEXT) \
COMMONOBJS = array.$(OBJEXT) \
bignum.$(OBJEXT) \
class.$(OBJEXT) \
compar.$(OBJEXT) \
@ -60,6 +61,11 @@ OBJS = array.$(OBJEXT) \
version.$(OBJEXT) \
$(MISSING)
OBJS = $(COMMONOBJS) prelude.$(OBJEXT)
PRELUDE_SCRIPTS = $(srcdir)/prelude.rb
PRELUDES = prelude.c miniprelude.c
SCRIPT_ARGS = --dest-dir="$(DESTDIR)" \
--extout="$(EXTOUT)" \
--mflags="$(MFLAGS)" \
@ -81,6 +87,8 @@ TESTWORKDIR = testwork
VCS = svn
COMPILE_PRELUDE = $(MINIRUBY) -I$(srcdir) $(srcdir)/compile_prelude.rb
all: main $(RDOCTARGET)
main: exts
@ -93,7 +101,7 @@ $(MKMAIN_CMD): $(MKFILES) $(PREP) $(RBCONFIG) $(LIBRUBY)
prog: $(PROGRAM) $(WPROGRAM)
miniruby$(EXEEXT): config.status $(LIBRUBY_A) $(MAINOBJ) $(MINIOBJS) $(OBJS) $(DMYEXT)
miniruby$(EXEEXT): config.status $(MAINOBJ) $(MINIOBJS) $(COMMONOBJS) $(DMYEXT)
$(PROGRAM): $(LIBRUBY) $(MAINOBJ) $(OBJS) $(EXTOBJS) $(SETUP) $(PREP)
@ -307,7 +315,7 @@ clean-ext::
distclean: distclean-ext distclean-local
distclean-local:: clean-local
@$(RM) $(MKFILES) config.h rbconfig.rb
@$(RM) config.cache config.log config.status
@$(RM) config.cache config.log config.status $(PRELUDES)
@$(RM) *~ *.bak *.stackdump core *.core gmon.out $(PREP)
distclean-ext::
@ -455,6 +463,12 @@ variable.$(OBJEXT): {$(VPATH)}variable.c $(RUBY_H_INCLUDES) \
version.$(OBJEXT): {$(VPATH)}version.c $(RUBY_H_INCLUDES) \
{$(VPATH)}version.h {$(VPATH)}revision.h
prelude.c: $(srcdir)/compile_prelude.rb $(RBCONFIG) $(PRELUDE_SCRIPTS) $(PREP)
$(COMPILE_PRELUDE) $(PRELUDE_SCRIPTS) $@
miniprelude.$(OBJEXT): {$(VPATH)}miniprelude.c $(RUBY_H_INCLUDES)
prelude.$(OBJEXT): {$(VPATH)}prelude.c $(RUBY_H_INCLUDES)
dist: $(PROGRAM)
$(RUNRUBY) $(srcdir)/distruby.rb

187
compile_prelude.rb Executable file
View file

@ -0,0 +1,187 @@
# This file is interpreted by miniruby.
# Do not use features that miniruby does not provide,
# including what's in prelude.rb.
require 'erb'
class Prelude
SRCDIR = File.dirname(__FILE__)
$:.unshift(SRCDIR)
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[/\A#{Regexp.quote(SRCDIR)}\/(.*?)(\.rb)?\z/om, 1]
end
def prelude_name(filename)
"<internal:" + prelude_base(filename) + ">"
end
def initialize(preludes)
@mkconf = nil
@have_sublib = false
@need_ruby_prefix = false
@preludes = {}
@mains = preludes.map {|filename| translate(filename)[0]}
end
def translate(filename, sub = false)
idx = @preludes[filename]
return idx if idx
lines = []
@preludes[filename] = result = [@preludes.size, filename, lines, sub]
File.readlines(filename).each do |line|
line.gsub!(/RbConfig::CONFIG\["(\w+)"\]/) {
key = $1
unless @mkconf
require './rbconfig'
@mkconf = RbConfig::MAKEFILE_CONFIG.merge('prefix'=>'#{TMP_RUBY_PREFIX}')
end
if RbConfig::MAKEFILE_CONFIG.has_key? key
val = RbConfig.expand("$(#{key})", @mkconf)
@need_ruby_prefix ||= /\A\#\{TMP_RUBY_PREFIX\}/ =~ val
c_esc(val)
else
"nil"
end
}
line.sub!(/require\s*\(?\s*(["'])(.*?)\1\)?/) do
orig, path = $&, $2
path = File.join(SRCDIR, path)
if File.exist?(path)
@have_sublib = true
"TMP_RUBY_PREFIX.require(#{translate(path, true)[0]})"
else
orig
end
end
lines << c_esc(line)
end
result
end
def emit(outfile)
init_name = outfile[/\w+(?=_prelude.c\b)/] || 'prelude'
erb = ERB.new(<<'EOS', nil, '%')
/* -*-c-*-
THIS FILE WAS AUTOGENERATED BY compile_prelude.rb. DO NOT EDIT.
soruces: <%= @preludes.map {|n,*| prelude_base(n)}.join(', ') %>
*/
#include "ruby.h"
VALUE rb_eval_prelude _((VALUE, const char *));
% preludes = @preludes.values.sort
% preludes.each {|i, prelude, lines, sub|
static const char prelude_name<%=i%>[] = <%=c_esc(prelude_name(*prelude))%>;
static const char prelude_code<%=i%>[] =
% lines.each {|line|
<%=line%>
% }
;
% }
#define PRELUDE_COUNT <%=@have_sublib ? preludes.size : 0%>
% if @have_sublib or @need_ruby_prefix
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
% if @have_sublib
static VALUE
prelude_require(VALUE self, VALUE nth)
{
struct prelude_env *ptr = DATA_PTR(self);
VALUE code;
const char *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 = rb_str_new(prelude_code<%=i%>, sizeof(prelude_code<%=i%>) - 1);
name = prelude_name<%=i%>;
break;
% end
% end
default:
return Qfalse;
}
rb_eval_prelude(code, name);
return Qtrue;
}
% end
void Init_<%=init_name%> _((void));
void
Init_<%=init_name%>()
{
% if @have_sublib or @need_ruby_prefix
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
rb_eval_prelude(rb_str_new(prelude_code<%=i%>, sizeof(prelude_code<%=i%>) - 1), prelude_name<%=i%>);
% end
% if @have_sublib or @need_ruby_prefix
rb_gc_force_recycle(prelude);
% end
#if 0
% preludes.length.times {|i|
puts(prelude_code<%=i%>);
% }
#endif
}
EOS
tmp = erb.result(binding)
open(outfile, 'w'){|f|
f << tmp
}
end
end
preludes = ARGV.dup
outfile = preludes.pop
Prelude.new(preludes).emit(outfile)

View file

@ -1829,6 +1829,8 @@ esac
RUBY_LIB_PATH="${RUBY_LIB_PREFIX}/${ruby_version}"
RUBY_SITE_LIB_PATH2="${RUBY_SITE_LIB_PATH}/${ruby_version}"
AC_DEFINE_UNQUOTED(RUBY_EXEC_PREFIX, "${RUBY_EXEC_PREFIX}")
AC_DEFINE_UNQUOTED(RUBY_LIB_PREFIX, ${RUBY_LIB_PREFIX})
AC_DEFINE_UNQUOTED(RUBY_LIB, "${RUBY_LIB_PATH}")
AC_DEFINE_UNQUOTED(RUBY_SITE_LIB, "${RUBY_SITE_LIB_PATH}")
AC_DEFINE_UNQUOTED(RUBY_SITE_LIB2, "${RUBY_SITE_LIB_PATH2}")

8
eval.c
View file

@ -6722,6 +6722,14 @@ eval(self, src, scope, file, line)
return result;
}
VALUE
rb_eval_prelude(src, name)
VALUE src;
const char *name;
{
return eval(ruby_top_self, src, Qnil, name, 1);
}
/*
* call-seq:
* eval(string [, binding [, filename [,lineno]]]) => obj

11
miniprelude.c Normal file
View file

@ -0,0 +1,11 @@
#include "ruby.h"
void Init_prelude _((void));
void Init_prelude()
{
/*
* Do nada, meaning miniruby does not support features implemented
* in prelude.rb.
*/
}

1
prelude.rb Normal file
View file

@ -0,0 +1 @@
# currently empty

20
ruby.c
View file

@ -254,6 +254,7 @@ ruby_init_loadpath()
{
#if defined LOAD_RELATIVE
char libpath[FILENAME_MAX+1];
size_t baselen;
char *p;
int rest;
#if defined _WIN32 || defined __CYGWIN__
@ -298,12 +299,16 @@ ruby_init_loadpath()
strcpy(libpath, ".");
p = libpath + 1;
}
#define PREFIX_PATH() rb_str_new(libpath, baselen)
rest = FILENAME_MAX - (p - libpath);
baselen = p - libpath;
rest = FILENAME_MAX - baselen;
#define RUBY_RELATIVE(path) (strncpy(p, (path), rest), libpath)
#else
static const char exec_prefix[] = RUBY_EXEC_PREFIX;
#define RUBY_RELATIVE(path) (path)
#define PREFIX_PATH() rubylib_mangled_path(exec_prefix, sizeof(exec_prefix)-1)
#endif
#define incpush(path) rb_ary_push(rb_load_path, rubylib_mangled_path2(path))
@ -338,6 +343,8 @@ ruby_init_loadpath()
if (rb_safe_level() == 0) {
incpush(".");
}
rb_const_set(rb_cObject, rb_intern("TMP_RUBY_PREFIX"), rb_obj_freeze(PREFIX_PATH()));
}
struct req_list {
@ -481,6 +488,16 @@ moreswitches(s)
return s;
}
static void ruby_prelude _((void));
void Init_prelude _((void));
static void
ruby_prelude()
{
Init_prelude();
rb_const_remove(rb_cObject, rb_intern("TMP_RUBY_PREFIX"));
}
static void
proc_options(argc, argv)
int argc;
@ -841,6 +858,7 @@ proc_options(argc, argv)
process_sflag();
ruby_init_loadpath();
ruby_prelude();
ruby_sourcefile = rb_source_filename(argv0);
if (e_script) {
require_libraries();