[前][次][番号順一覧][スレッド一覧]

ruby-changes:15064

From: nobu <ko1@a...>
Date: Mon, 15 Mar 2010 18:53:49 +0900 (JST)
Subject: [ruby-changes:15064] Ruby:r26940 (mvm): * merged from trunk r26885:26939.

nobu	2010-03-15 18:53:15 +0900 (Mon, 15 Mar 2010)

  New Revision: 26940

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=26940

  Log:
    * merged from trunk r26885:26939.

  Modified files:
    branches/mvm/.merged-trunk-revision
    branches/mvm/ChangeLog
    branches/mvm/NEWS
    branches/mvm/array.c
    branches/mvm/compile.c
    branches/mvm/enc/trans/emoji.trans
    branches/mvm/enc/trans/single_byte.trans
    branches/mvm/enum.c
    branches/mvm/ext/nkf/nkf-utf8/nkf.c
    branches/mvm/ext/tk/extconf.rb
    branches/mvm/ext/tk/lib/tk.rb
    branches/mvm/ext/tk/tkutil/tkutil.c
    branches/mvm/file.c
    branches/mvm/gem_prelude.rb
    branches/mvm/include/ruby/intern.h
    branches/mvm/include/ruby/io.h
    branches/mvm/io.c
    branches/mvm/iseq.c
    branches/mvm/lib/rubygems.rb
    branches/mvm/lib/uri/common.rb
    branches/mvm/lib/webrick/httpservlet/cgihandler.rb
    branches/mvm/load.c
    branches/mvm/random.c
    branches/mvm/ruby.c
    branches/mvm/symbian/README.SYMBIAN
    branches/mvm/symbian/configure.bat
    branches/mvm/symbian/setup
    branches/mvm/test/ruby/enc/test_emoji.rb
    branches/mvm/test/ruby/test_array.rb
    branches/mvm/test/ruby/test_enum.rb
    branches/mvm/test/ruby/test_file.rb
    branches/mvm/test/ruby/test_file_exhaustive.rb
    branches/mvm/test/ruby/test_io.rb
    branches/mvm/test/ruby/test_rand.rb
    branches/mvm/test/uri/test_common.rb
    branches/mvm/tool/compile_prelude.rb
    branches/mvm/tool/file2lastrev.rb
    branches/mvm/tool/transcode-tblgen.rb
    branches/mvm/version.h

Index: mvm/array.c
===================================================================
--- mvm/array.c	(revision 26939)
+++ mvm/array.c	(revision 26940)
@@ -1600,7 +1600,7 @@
 		val = tmp;
 		goto str_join;
 	    }
-	    tmp = rb_check_convert_type(val, T_ARRAY, "Array", "to_a");
+	    tmp = rb_check_convert_type(val, T_ARRAY, "Array", "to_ary");
 	    if (!NIL_P(tmp)) {
 		obj = val;
 		val = tmp;
Index: mvm/include/ruby/intern.h
===================================================================
--- mvm/include/ruby/intern.h	(revision 26939)
+++ mvm/include/ruby/intern.h	(revision 26940)
@@ -365,6 +365,7 @@
 char *rb_path_last_separator(const char *);
 char *rb_path_end(const char *);
 VALUE rb_file_directory_p(VALUE,VALUE);
+int rb_is_absolute_path(const char *);
 /* gc.c */
 void ruby_set_stack_size(size_t);
 NORETURN(void rb_memerror(void));
Index: mvm/include/ruby/io.h
===================================================================
--- mvm/include/ruby/io.h	(revision 26939)
+++ mvm/include/ruby/io.h	(revision 26940)
@@ -101,7 +101,7 @@
 #define MakeOpenFile(obj, fp) do {\
     if (RFILE(obj)->fptr) {\
 	rb_io_close(obj);\
-	free(RFILE(obj)->fptr);\
+	rb_io_fptr_finalize(RFILE(obj)->fptr);\
 	RFILE(obj)->fptr = 0;\
     }\
     fp = 0;\
@@ -166,8 +166,6 @@
 int rb_io_read_pending(rb_io_t*);
 DEPRECATED(void rb_read_check(FILE*));
 
-int ruby_absolute_path_p(const char*);
-
 #if defined(__cplusplus)
 #if 0
 { /* satisfy cc-mode */
Index: mvm/ChangeLog
===================================================================
--- mvm/ChangeLog	(revision 26939)
+++ mvm/ChangeLog	(revision 26940)
@@ -1,3 +1,198 @@
+Mon Mar 15 18:33:36 2010  Nobuyoshi Nakada  <nobu@r...>
+
+	* random.c (default_rand): removed initial buffer.
+
+	* random.c (Init_RandomSeed): initialize seed of default random.
+
+	* random.c (Init_RandomSeed2): turn the seed to Bignum object.
+
+Mon Mar 15 17:28:30 2010  Yukihiro Matsumoto  <matz@r...>
+
+	* io.c (rb_io_print): RDoc update.  a patch from Daniel Kelley
+	  in [ruby-core:28643].
+
+Mon Mar 15 14:06:07 2010  Nobuyoshi Nakada  <nobu@r...>
+
+	* random.c (next_state): no initialization here.
+
+	* random.c (default_mt): always return initialized MT.
+
+Mon Mar 15 11:49:48 2010  NARUSE, Yui  <naruse@r...>
+
+	* random.c (rb_reset_random_seed): set seed in this.
+	  [ruby-core:28655]
+
+Mon Mar 15 10:26:02 2010  NARUSE, Yui  <naruse@r...>
+
+	* ext/nkf/nkf-utf8/nkf.c: import latest nkf. [master 9306cb0]
+	  this also fixes [ruby-dev:40607]
+
+Mon Mar 15 09:34:17 2010  NARUSE, Yui  <naruse@r...>
+
+	* lib/uri/common.rb (URI.encode_www_component):
+	  call str.to_s at first.
+
+Mon Mar 15 09:36:22 2010  Nobuyoshi Nakada  <nobu@r...>
+
+	* symbian/README.SYMBIAN: fixed broken patch and converted to
+	  unified diff.
+
+Mon Mar 15 07:51:05 2010  Nobuyoshi Nakada  <nobu@r...>
+
+	* file.c (Init_File): do not define File::ALT_SEPARATOR on cygwin.
+
+Mon Mar 15 07:41:00 2010  Nobuyoshi Nakada  <nobu@r...>
+
+	* file.c (realpath_rec): use same cache.
+
+	* file.c (realpath_internal): regulate separators in prefix.
+	  [ruby-core:28653]
+
+	* file.c (FILE_ALT_SEPARATOR): separated condition.
+
+Mon Mar 15 04:41:25 2010  Nobuyoshi Nakada  <nobu@r...>
+
+	* io.c (rb_io_each_codepoint): read directly when readconv is
+	  needed but internal encoding is not set.  [ruby-core:28650]
+
+Mon Mar 15 04:18:31 2010  Nobuyoshi Nakada  <nobu@r...>
+
+	* tool/file2lastrev.rb (VCS::{SVN,GIT}#get_revisions):
+	  use block argument 'path' to get the path given by super.
+
+Mon Mar 15 02:43:59 2010  Tanaka Akira  <akr@f...>
+
+	* tool/transcode-tblgen.rb (Action#hash): defined.
+	  (Action#eql?): ditto.
+	  (Action#==): ditto.
+
+Mon Mar 15 01:52:46 2010  Tanaka Akira  <akr@f...>
+
+	* tool/transcode-tblgen.rb: refactored.
+
+Mon Mar 15 01:18:31 2010  Alexander Zavorine  <alexandre.zavorine@n...>
+
+	* symbian/setup (*.pkg): Ruby Core installation separated from standard extensions.
+
+	* symbian/configure.bat: ditto.
+
+	* symbian/README.SYMBIAN: ditto.
+
+	* symbian/setup (config.h): support for 2nd internal drive added.
+
+Mon Mar 15 00:11:23 2010  NARUSE, Yui  <naruse@r...>
+
+	* tool/file2lastrev.rb (VCS::GIT_SVN#get_revisions) :
+	  use block argument 'path' to get the path given by super.
+
+	* tool/file2lastrev.rb (VCS::GIT#get_revisions):
+	  use double quotes for Windows.
+	  patched by Vladimir Sizikov [ruby-core:28651]
+
+Sun Mar 14 22:38:31 2010  Tanaka Akira  <akr@f...>
+
+	* tool/transcode-tblgen.rb: consider valid_encoding for max_input.
+
+Sun Mar 14 15:46:09 2010  Tanaka Akira  <akr@f...>
+
+	* enc/trans/emoji.trans: fix nomap_table.
+
+Sun Mar 14 09:50:03 2010  Nobuyoshi Nakada  <nobu@r...>
+
+	* compile.c (insn_data_to_s_detail), iseq.c (insn_operand_intern):
+	  fixed format specifiers.
+
+Sun Mar 14 07:20:17 2010  Yukihiro Matsumoto  <matz@r...>
+
+	* file.c (EXPAND_PATH_BUFFER): make it back to usascii, to prevent
+	  infinite loop on some platform. [ruby-dev:40629]
+
+Sun Mar 14 02:40:38 2010  Tanaka Akira  <akr@f...>
+
+	* tool/transcode-tblgen.rb: reject ambiguous mapping.
+
+	* enc/trans/single_byte.trans: remove ambiguous maping such as
+	  \xD6 -> U+05F2 and \xD6\xC7 -> U+FB1F in Windows-1255
+
+Sat Mar 13 23:48:27 2010  Yukihiro Matsumoto  <matz@r...>
+
+	* file.c (file_expand_path): should not just copy the encoding
+	  from fname.  [ruby-core:28635]
+
+	* file.c (EXPAND_PATH_BUFFER): set filesystem_encoding, not
+	  usascii for path buffer.
+
+Sat Mar 13 17:48:43 2010  Nobuyoshi Nakada  <nobu@r...>
+
+	* tool/file2lastrev.rb: refactord.  fixed changed revision of git.
+
+Sat Mar 13 15:44:20 2010  Yukihiro Matsumoto  <matz@r...>
+
+	* io.c (rb_io_print): should not print field separator at the end
+	  of arguments.  [ruby-talk:358633]
+
+Sat Mar 13 14:49:55 2010  Yukihiro Matsumoto  <matz@r...>
+
+	* enum.c (enum_join): remove Enumerable#join. [ruby-core:24786]
+
+	* array.c (ary_join_1): use #to_ary to detect recursive array.
+
+Sat Mar 13 12:26:13 2010  Nobuyoshi Nakada  <nobu@r...>
+
+	* include/ruby/io.h (MakeOpenFile): finalize fptr to get rid of
+	  memory leak.
+
+Sat Mar 13 11:14:26 2010  Shugo Maeda  <shugo@r...>
+
+	* load.c (rb_get_expanded_load_path): expand paths if any item in $:
+	  is not a string.
+
+Sat Mar 13 10:16:32 2010  Shugo Maeda  <shugo@r...>
+
+	* load.c (rb_get_expanded_load_path): does not expand paths if all
+	  the items in $: are absolute paths.  [ruby-core:28113]
+
+Sat Mar 13 10:03:52 2010  Hidetoshi NAGAI  <nagai@a...>
+
+	* ext/tk/extconf.rb: fix [Bug #2840] Tk doesn't built in mingw.
+
+Sat Mar 13 03:24:15 2010  Tanaka Akira  <akr@f...>
+
+	* tool/transcode-tblgen.rb: show consumed time at last.
+
+Sat Mar 13 00:44:20 2010  Nobuyoshi Nakada  <nobu@r...>
+
+	* file.c (rb_file_s_basename): check encoding of suffix.
+
+Sat Mar 13 00:11:05 2010  Nobuyoshi Nakada  <nobu@r...>
+
+	* ruby.c (ruby_init_loadpath_safe): mark initial load paths.
+
+	* gem_prelude.rb (push_all_highest_version_gems_on_load_path):
+	  search insertion position by initial load path mark.
+
+	* lib/rubygems.rb (Gem.load_path_insert_index): ditto.
+
+Fri Mar 12 21:34:00 2010  Kenta Murata  <mrkn@m...>
+
+	* NEWS: emoji encodings.
+
+Fri Mar 12 17:14:12 2010  NARUSE, Yui  <naruse@r...>
+
+	* lib/uri/common.rb (URI.encode_www_form): new method to
+	  generate URL-encoded form data. [ruby-dev:39246]
+
+	* lib/uri/common.rb (URI.encode_www_component,
+	  URI.decode_www_component): new method for encode/decode
+	  a name/value of HTML form.
+
+Fri Mar 12 17:36:35 2010  NARUSE, Yui  <naruse@r...>
+
+	* lib/webrick/httpservlet/cgihandler.rb
+	  (WEBrick::HTTPServlet::CGIHandler#do_GET):
+	  set binary mode for tempfile.
+	  http://pc12.2ch.net/test/read.cgi/tech/1265467681/286
+
 Fri Mar 12 13:52:00 2010  Kenta Murata  <mrkn@m...>
 
 	* tool/compile_prelude.rb: TMP_RUBY_PREFIX should replace
Index: mvm/gem_prelude.rb
===================================================================
--- mvm/gem_prelude.rb	(revision 26939)
+++ mvm/gem_prelude.rb	(revision 26940)
@@ -267,7 +267,7 @@
           require_paths.first.instance_variable_set(:@gem_prelude_index, true)
         end
         # gem directories must come after -I and ENV['RUBYLIB']
-        $:[$:.index(ConfigMap[:sitelibdir]),0] = require_paths
+        $:[$:.index{|e|e.instance_variable_defined?(:@gem_prelude_index)}||-1,0] = require_paths
       end
 
       def const_missing(constant)
Index: mvm/enc/trans/emoji.trans
===================================================================
--- mvm/enc/trans/emoji.trans	(revision 26939)
+++ mvm/enc/trans/emoji.trans	(revision 26940)
@@ -6,7 +6,7 @@
   nomap_table = [
     ["{00-7f}", :nomap],
     ["{c2-df}{80-bf}", :nomap0],
-    ["e0{a0-df}{80-bf}", :nomap0],
+    ["e0{a0-bf}{80-bf}", :nomap0],
     ["{e1-ec}{80-bf}{80-bf}", :nomap0],
     ["ed{80-9f}{80-bf}", :nomap0],
     ["{ee-ef}{80-bf}{80-bf}", :nomap0],
Index: mvm/enc/trans/single_byte.trans
===================================================================
--- mvm/enc/trans/single_byte.trans	(revision 26939)
+++ mvm/enc/trans/single_byte.trans	(revision 26940)
@@ -24,7 +24,7 @@
     tbl_to_ucs = control1_if_needed + eval(name.gsub(/-/, '_') + "_TO_UCS_TBL")
     set_valid_byte_pattern(name, '1byte')
     code = ''
-    code << transcode_tblgen(name, "UTF-8", [["{00-7f}", :nomap], *tbl_to_ucs])
+    code << transcode_tblgen(name, "UTF-8", [["{00-7f}", :nomap], *tbl_to_ucs.reject {|a, b| a.length != 2 }])
     code << "\n"
     code << transcode_tblgen("UTF-8", name, [["{00-7f}", :nomap], *tbl_to_ucs.map {|a,b| [b,a] }])
     code
Index: mvm/iseq.c
===================================================================
--- mvm/iseq.c	(revision 26939)
+++ mvm/iseq.c	(revision 26940)
@@ -795,7 +795,7 @@
 	break;
 
       case TS_IC:
-	ret = rb_sprintf("<ic:%d>", (struct iseq_inline_cache_entry *)op - iseq->ic_entries);
+	ret = rb_sprintf("<ic:%"PRIdPTRDIFF">", (struct iseq_inline_cache_entry *)op - iseq->ic_entries);
 	break;
 
       case TS_CDHASH:
Index: mvm/enum.c
===================================================================
--- mvm/enum.c	(revision 26939)
+++ mvm/enum.c	(revision 26940)
@@ -1333,7 +1333,7 @@
 
 /*
  *  call-seq:
- *     enum.min_by {| obj| block }   => obj
+ *     enum.min_by {|obj| block }   => obj
  *
  *  Returns the object in <i>enum</i> that gives the minimum
  *  value from the given block.
@@ -1376,7 +1376,7 @@
 
 /*
  *  call-seq:
- *     enum.max_by {| obj| block }   => obj
+ *     enum.max_by {|obj| block }   => obj
  *
  *  Returns the object in <i>enum</i> that gives the maximum
  *  value from the given block.
@@ -1470,7 +1470,7 @@
 
 /*
  *  call-seq:
- *     enum.minmax_by {| obj| block }   => [min, max]
+ *     enum.minmax_by {|obj| block }   => [min, max]
  *
  *  Returns two elements array array containing the objects in
  *  <i>enum</i> that gives the minimum and maximum values respectively
@@ -2417,15 +2417,18 @@
  *
  *  If the block needs to maintain state over multiple elements,
  *  local variables can be used.
- *  For example, monotonically increasing elements can be chunked as follows.
+ *  For example, three or more consecutive increasing numbers can be squashed
+ *  as follows:
  *
- *    a = [3,1,4,1,5,9,2,6,5,3,5]
- *    n = 0
- *    p a.slice_before {|elt|
- *      prev, n = n, elt
- *      prev > elt
- *    }.to_a
- *    #=> [[3], [1, 4], [1, 5, 9], [2, 6], [5], [3, 5]]
+ *    a = [0,2,3,4,6,7,9] 
+ *    prev = a[0]
+ *    p a.slice_before {|e|
+ *      prev, prev2 = e, prev
+ *      prev2 + 1 != e
+ *    }.map {|es|
+ *      es.length <= 2 ? es.join(",") : "#{es.first}-#{es.last}"
+ *    }.join(",")
+ *    #=> "0,2-4,6,7,9"
  *
  *  However local variables are not appropriate to maintain state
  *  if the result enumerator is used twice or more.
@@ -2519,25 +2522,6 @@
 }
 
 /*
- *  call-seq:
- *     enum.join(sep=$,)    -> str
- *
- *  Returns a string created by converting each element of the
- *  <i>enum</i> to a string, separated by <i>sep</i>.
- */
-
-static VALUE
-enum_join(int argc, VALUE *argv, VALUE obj)
-{
-    VALUE sep;
-
-    rb_scan_args(argc, argv, "01", &sep);
-    if (NIL_P(sep)) sep = rb_output_fs;
-
-    return rb_ary_join(enum_to_a(0, 0, obj), sep);
-}
-
-/*
  *  The <code>Enumerable</code> mixin provides collection classes with
  *  several traversal and searching methods, and with the ability to
  *  sort. The class must provide a method <code>each</code>, which
@@ -2612,7 +2596,6 @@
     rb_define_method(rb_mEnumerable, "drop", enum_drop, 1);
     rb_define_method(rb_mEnumerable, "drop_while", enum_drop_while, 0);
     rb_define_method(rb_mEnumerable, "cycle", enum_cycle, -1);
-    rb_define_method(rb_mEnumerable, "join", enum_join, -1);
     rb_define_method(rb_mEnumerable, "chunk", enum_chunk, -1);
     rb_define_method(rb_mEnumerable, "slice_before", enum_slice_before, -1);
 }
Index: mvm/io.c
===================================================================
--- mvm/io.c	(revision 26939)
+++ mvm/io.c	(revision 26940)
@@ -2894,9 +2894,14 @@
 			 rb_enc_name(fptr->encs.enc));
 	    }
 	    n = MBCLEN_CHARFOUND_LEN(r);
-	    c = rb_enc_codepoint(fptr->cbuf+fptr->cbuf_off,
-				 fptr->cbuf+fptr->cbuf_off+fptr->cbuf_len,
-				 fptr->encs.enc);
+	    if (fptr->encs.enc) {
+		c = rb_enc_codepoint(fptr->cbuf+fptr->cbuf_off,
+				     fptr->cbuf+fptr->cbuf_off+fptr->cbuf_len,
+				     fptr->encs.enc);
+	    }
+	    else {
+		c = (unsigned char)fptr->cbuf[fptr->cbuf_off];
+	    }
 	    fptr->cbuf_off += n;
 	    fptr->cbuf_len -= n;
 	    rb_yield(UINT2NUM(c));
@@ -4495,7 +4500,7 @@
 #if USE_OPENAT
     data.base = (base && base->fd != -1) ? base->fd : DEFAULT_BASE_FD;
 #else
-    if (base && !ruby_absolute_path_p(RSTRING_PTR(fname))) {
+    if (base && !rb_is_absolute_path(RSTRING_PTR(fname))) {
 	VALUE fullpath = Qnil;
 	if (base->fd != -1) {
 	    char *basecwd;
@@ -5964,7 +5969,9 @@
  *     ios.print(obj, ...)     => nil
  *
  *  Writes the given object(s) to <em>ios</em>. The stream must be
- *  opened for writing. If the output record separator (<code>$\\</code>)
+ *  opened for writing. If the output field separator (<code>$,</code>)
+ *  is not <code>nil</code>, it will be inserted between each object.
+ *  If the output record separator (<code>$\\</code>)
  *  is not <code>nil</code>, it will be appended to the output. If no
  *  arguments are given, prints <code>$_</code>. Objects that aren't
  *  strings will be converted by calling their <code>to_s</code> method.
@@ -5991,10 +5998,10 @@
 	argv = &line;
     }
     for (i=0; i<argc; i++) {
-	rb_io_write(out, argv[i]);
-	if (!NIL_P(rb_output_fs)) {
+	if (!NIL_P(rb_output_fs) && i>0) {
 	    rb_io_write(out, rb_output_fs);
 	}
+	rb_io_write(out, argv[i]);
     }
     if (argc > 0 && !NIL_P(rb_output_rs)) {
 	rb_io_write(out, rb_output_rs);
Index: mvm/load.c
===================================================================
--- mvm/load.c	(revision 26939)
+++ mvm/load.c	(revision 26940)
@@ -37,10 +37,19 @@
 rb_get_expanded_load_path(void)
 {
     VALUE load_path = rb_get_load_path();
-    VALUE ary = rb_ary_new2(RARRAY_LEN(load_path));
+    VALUE ary;
     long i;
 
     for (i = 0; i < RARRAY_LEN(load_path); ++i) {
+	VALUE str = rb_check_string_type(RARRAY_PTR(load_path)[i]);
+	if (NIL_P(str) || !rb_is_absolute_path(RSTRING_PTR(str)))
+	    goto relative_path_found;
+    }
+    return load_path;
+
+  relative_path_found:
+    ary = rb_ary_new2(RARRAY_LEN(load_path));
+    for (i = 0; i < RARRAY_LEN(load_path); ++i) {
 	VALUE path = rb_file_expand_path(RARRAY_PTR(load_path)[i], Qnil);
 	rb_str_freeze(path);
 	rb_ary_push(ary, path);
Index: mvm/lib/webrick/httpservlet/cgihandler.rb
===================================================================
--- mvm/lib/webrick/httpservlet/cgihandler.rb	(revision 26939)
+++ mvm/lib/webrick/httpservlet/cgihandler.rb	(revision 26940)
@@ -32,9 +32,9 @@
         status = -1
 
         cgi_in = IO::popen(@cgicmd, "wb")
-        cgi_out = Tempfile.new("webrick.cgiout.", @tempdir)
+        cgi_out = Tempfile.new("webrick.cgiout.", @tempdir, mode: IO::BINARY)
         cgi_out.set_encoding("ASCII-8BIT")
-        cgi_err = Tempfile.new("webrick.cgierr.", @tempdir)
+        cgi_err = Tempfile.new("webrick.cgierr.", @tempdir, mode: IO::BINARY)
         cgi_err.set_encoding("ASCII-8BIT")
         begin
           cgi_in.sync = true
Index: mvm/lib/rubygems.rb
===================================================================
--- mvm/lib/rubygems.rb	(revision 26939)
+++ mvm/lib/rubygems.rb	(revision 26940)
@@ -254,8 +254,6 @@
       File.join spec.full_gem_path, path
     end
 
-    sitelibdir = ConfigMap[:sitelibdir]
-
     # gem directories must come after -I and ENV['RUBYLIB']
     insert_index = load_path_insert_index
 
@@ -570,23 +568,9 @@
 
   ##
   # The index to insert activated gem paths into the $LOAD_PATH.
-  #
-  # Defaults to the site lib directory unless gem_prelude.rb has loaded paths,
-  # then it inserts the activated gem's paths before the gem_prelude.rb paths
-  # so you can override the gem_prelude.rb default $LOAD_PATH paths.
 
   def self.load_path_insert_index
-    index = $LOAD_PATH.index ConfigMap[:sitelibdir]
-
-    $LOAD_PATH.each_with_index do |path, i|
-      if path.instance_variables.include?(:@gem_prelude_index) or
-        path.instance_variables.include?('@gem_prelude_index') then
-        index = i
-        break
-      end
-    end
-
-    index
+    $LOAD_PATH.index {|path| path.instance_variable_defined?(:@gem_prelude_index)}
   end
 
   ##
Index: mvm/lib/uri/common.rb
===================================================================
--- mvm/lib/uri/common.rb	(revision 26939)
+++ mvm/lib/uri/common.rb	(revision 26940)
@@ -716,6 +716,94 @@
     DEFAULT_PARSER.make_regexp(schemes)
   end
 
+  # :nodoc:
+  TBLENCWWWCOMP_ = {}
+
+  # :nodoc:
+  TBLDECWWWCOMP_ = {}
+
+  # Encode given +str+ to URL-encoded form data.
+  #
+  # This doesn't convert *, -, ., 0-9, A-Z, _, a-z,
+  # does convert SP to +, and convert others to %XX.
+  #
+  # This refers http://www.w3.org/TR/html5/forms.html#url-encoded-form-data
+  #
+  # See URI.decode_www_component(str), URI.encode_www_form(enum)
+  def self.encode_www_component(str)
+    if TBLENCWWWCOMP_.empty?
+      256.times do |i|
+        case i
+        when 0x20
+          TBLENCWWWCOMP_[' '] = '+'
+        when 0x2A, 0x2D, 0x2E, 0x30..0x39, 0x41..0x5A, 0x5F, 0x61..0x7A
+        else
+          TBLENCWWWCOMP_[i.chr] = '%%%X' % i
+        end
+      end
+      TBLENCWWWCOMP_.freeze
+    end
+    str = str.to_s.dup
+    enc = str.encoding
+    str.force_encoding(Encoding::ASCII_8BIT)
+    str.gsub!(/[^*\-.0-9A-Z_a-z]/, TBLENCWWWCOMP_)
+    str.force_encoding(enc)
+  end
+
+  # Decode given +str+ of URL-encoded form data.
+  #
+  # This decods + to SP.
+  #
+  # See URI.encode_www_component(str)
+  def self.decode_www_component(str)
+    if TBLDECWWWCOMP_.empty?
+      256.times do |i|
+        case i
+        when 0x20
+          TBLDECWWWCOMP_['+'] = ' '
+        else
+          h, l = i>>4, i&15
+          TBLDECWWWCOMP_['%%%X%X' % [h, l]] = i.chr
+          TBLDECWWWCOMP_['%%%x%X' % [h, l]] = i.chr
+          TBLDECWWWCOMP_['%%%X%x' % [h, l]] = i.chr
+          TBLDECWWWCOMP_['%%%x%x' % [h, l]] = i.chr
+        end
+      end
+      TBLDECWWWCOMP_.freeze
+    end
+    str.gsub(/\+|%\h\h/, TBLDECWWWCOMP_)
+  end
+
+  # Generate URL-encoded form data from given +enum+.
+  #
+  # This generates application/x-www-form-urlencoded data defined in HTML5
+  # from given an Enumerable object.
+  #
+  # This internally uses URI.encode_www_component(str).
+  #
+  # This doesn't convert encodings of give items, so convert them before call
+  # this method if you want to send data as other than original encoding or
+  # mixed encoding data.
+  #
+  # This doesn't treat files. When you send a file, use multipart/form-data.
+  #
+  # This refers http://www.w3.org/TR/html5/forms.html#url-encoded-form-data
+  #
+  # See URI.encode_www_component(str)
+  def self.encode_www_form(enum)
+    str = nil
+    enum.each do |k,v|
+      if str
+        str << '&'
+      else
+        str = ''.force_encoding(Encoding::US_ASCII)
+      end
+      str << encode_www_component(k)
+      str << '='
+      str << encode_www_component(v)
+    end
+    str
+  end
 end
 
 module Kernel
Index: mvm/compile.c
===================================================================
--- mvm/compile.c	(revision 26939)
+++ mvm/compile.c	(revision 26940)
@@ -4973,7 +4973,7 @@
 
 	for (j = 0; types[j]; j++) {
 	    char type = types[j];
-	    printf("str: %p, type: %c\n", str, type);
+	    printf("str: %"PRIxVALUE", type: %c\n", str, type);
 
 	    switch (type) {
 	      case TS_OFFSET:	/* label(destination position) */
Index: mvm/symbian/setup
===================================================================
--- mvm/symbian/setup	(revision 26939)
+++ mvm/symbian/setup	(revision 26940)
@@ -187,7 +187,7 @@
 @echo>>$(1) #define RUBY_LIB_VERSION_STYLE 3
 @echo>>$(1) #define RUBY_LIB_PREFIX "C:/Data/Ruby/lib"
 @echo>>$(1) #define RUBY_SITE_LIB "E:/Data/Ruby/lib"
-@echo>>$(1) #define RUBY_VENDOR_LIB "C:/Data/Ruby/lib"
+@echo>>$(1) #define RUBY_VENDOR_LIB "F:/Data/Ruby/lib"
 @echo>>$(1) #define RUBY_PLATFORM "$(arch)"
 endef
 
@@ -340,6 +340,7 @@
 define ext_mmp
 @echo>$(1)$(2).mmp TARGET $(2).dll
 @echo>>$(1)$(2).mmp TARGETTYPE DLL
+@echo>>$(1)$(2).mmp EPOCALLOWDLLDATA
 @echo>>$(1)$(2).mmp UID 0x10004262 $(3)
 @echo>>$(1)$(2).mmp VENDORID 0
 @echo>>$(1)$(2).mmp SECUREID $(3)
@@ -391,7 +392,20 @@
 @echo>>$(1) "$(EPOCROOT)epoc32\release\gcce\urel\Ruby.exe"-"!:\sys\bin\Ruby.exe"
 endef
 
+define core_ext_pkg
+@echo>$(1) ^&EN
 
+@echo>>$(1) #{"Ruby Core Extensions"},($(STRINGIO_UID)),$(MAJOR),$(MINOR),$(TEENY)
+
+@echo>>$(1) %%{"Symbian Research"}
+
+@echo>>$(1) :"Symbian Research"
+
+@echo>>$(1) ($(RUBY_UID)), $(MAJOR),$(MINOR),$(TEENY), {"Symbian Ruby"}
+
+@echo>>$(1) [0x101F7961], 0, 0, 0, {"S60ProductID"}
+endef
+
 define ext_pkg
 @echo>>$(1) "$(EPOCROOT)epoc32\release\gcce\urel\$(2).dll"-"!:\sys\bin\$(2).dll"
 @echo>>$(1) "$(EPOCROOT)epoc32\release\gcce\urel\$(2).dll"-"!:\Data\Ruby\lib\$(MAJOR).$(MINOR).$(TEENY)\$(arch)\$(2).dll"
Index: mvm/symbian/configure.bat
===================================================================
--- mvm/symbian/configure.bat	(revision 26939)
+++ mvm/symbian/configure.bat	(revision 26940)
@@ -104,9 +104,10 @@
 echo>> ~tmp~.mak ^	@if not exist sis\nul md sis
 echo>> ~tmp~.mak ^	$(call ruby_pkg,sis\ruby.pkg)
 echo>> ~tmp~.mak ifndef EXTSTATIC
-echo>> ~tmp~.mak ^	$(call ext_bigdecimal,sis\ruby.pkg)
-echo>> ~tmp~.mak ^	$(call ext_pkg,sis\ruby.pkg,stringio)
-echo>> ~tmp~.mak ^	$(call ext_pkg,sis\ruby.pkg,zlib)
+echo>> ~tmp~.mak ^	$(call core_ext_pkg,sis\ruby_core_ext.pkg)
+echo>> ~tmp~.mak ^	$(call ext_bigdecimal,sis\ruby_core_ext.pkg)
+echo>> ~tmp~.mak ^	$(call ext_pkg,sis\ruby_core_ext.pkg,stringio)
+echo>> ~tmp~.mak ^	$(call ext_pkg,sis\ruby_core_ext.pkg,zlib)
 echo>> ~tmp~.mak ^	@if not exist eabi\nul md eabi
 echo>> ~tmp~.mak ^	$(call ext_def,eabi\,stringio)
 echo>> ~tmp~.mak ^	$(call ext_def,eabi\,bigdecimal)
Index: mvm/symbian/README.SYMBIAN
===================================================================
--- mvm/symbian/README.SYMBIAN	(revision 26939)
+++ mvm/symbian/README.SYMBIAN	(revision 26940)
@@ -8,68 +8,58 @@
 
     Note: if you want to build dynamic extensions support you need to install the latest version of GCC compiler from http://www.codesourcery.com/gnu_toolchains/arm/portal/release643. After that you need to apply a patch below to a header file (SDK_ROOT)\epoc32\include\gcce\gcce.h
 
-11c11
-<
----
-> @released
-18a19
->
-21a23
->
-24a27,29
-> #define IMPORT_D __declspec(dllimport)
-> #define EXPORT_D __declspec(dllexport)
->
-81,82c86,87
-< #define __NAKED__ __asm
-< #define ____ONLY_USE_NAKED_IN_CIA____ __asm
----
-> #define __NAKED__ __declspec(naked)
-> #define ____ONLY_USE_NAKED_IN_CIA____ __declspec(naked)
-92,96c97,98
-<     namespace std {
-<         extern "C" {
-< #endif  /* __cplusplus */
-<
-< typedef struct __va_list { void *__ap; } va_list;
----
->     namespace std { extern "C" {
-> #endif
-97a100,104
->     #if __GNUC__ < 4
->     typedef struct __va_list { void *__ap; } va_list;
->     #else
->     typedef __builtin_va_list va_list;
->     #endif
-100,102c107
-< 	}  /* extern "C" */
-<     }  /* namespace std */
-<
----
-> 	} }
-105a111
-> #if __GNUC__ < 4
-107,109c113,119
-< #define va_arg(ap, type) __builtin_va_arg(ap.__ap, type)
-< #define va_end(ap) __builtin_va_end(ap.__ap)
-<
----
-> #define va_arg(ap, type)    __builtin_va_arg(ap.__ap, type)
-> #define va_end(ap)          __builtin_va_end(ap.__ap)
-> #else
-> #define va_start(ap, parmN) __builtin_va_start(ap, parmN)
-> #define va_arg(ap, type)    __builtin_va_arg(ap, type)
-> #define va_end(ap)          __builtin_va_end(ap)
-> #endif
-140,141c150,152
-< // Deal with operator new issues here
-< #include "../symcpp.h"
----
-> #ifndef __SYMBIAN_STDCPP_SUPPORT__
-> 	#include "../symcpp.h"
-> #endif
-151a163
->
+===================================================================
+--- Epoc32/include/gcce/gcce.h
++++ Epoc32/include/gcce/gcce.h
+@@ -22,4 +22,6 @@
+ #define IMPORT_C __declspec(dllimport) 
+ #define EXPORT_C __declspec(dllexport)
++#define IMPORT_D __declspec(dllimport)
++#define EXPORT_D __declspec(dllexport)
+ 
+ 
+@@ -79,6 +81,6 @@
+ 
+ // __NAKED__ from cpudefs.h
+-#define __NAKED__ __asm
+-#define ____ONLY_USE_NAKED_IN_CIA____ __asm
++#define __NAKED__ __declspec(naked)
++#define ____ONLY_USE_NAKED_IN_CIA____ __declspec(naked)
+ 
+ // Int64 and Uint64 from nkern\nklib.h
+@@ -94,5 +96,9 @@
+ #endif  /* __cplusplus */
+ 
++#if __GNUC__ < 4
+ typedef struct __va_list { void *__ap; } va_list;
++#else
++typedef __builtin_va_list va_list;
++#endif
+ 
+ 
+@@ -104,7 +110,13 @@
+ #endif
+ 
++#if __GNUC__ < 4
+ #define va_start(ap, parmN) __builtin_va_start(ap.__ap, parmN)
+ #define va_arg(ap, type) __builtin_va_arg(ap.__ap, type)
+ #define va_end(ap) __builtin_va_end(ap.__ap)
++#else
++#define va_start(ap, parmN) __builtin_va_start(ap, parmN)
++#define va_arg(ap, type) __builtin_va_arg(ap, type)
++#define va_end(ap) __builtin_va_end(ap)
++#endif
+ 
+ 
+@@ -139,5 +151,7 @@
+ 
+ // Deal with operator new issues here
++#ifndef __SYMBIAN_STDCPP_SUPPORT__
+ #include "..\symcpp.h"
++#endif
+ 
+ #ifdef __cplusplus
+===================================================================
 
 
 (2) If you want to build from SVN source, following command line binaries are required that are not a part of Symbain SDK.
@@ -88,13 +78,16 @@
      'abld freeze gcce ruby'
      'abld build gcce urel'
 
-(3) Run `makesis ruby.pkg' from symbian\sis directory
+(3) Run 'makesis ruby.pkg' from symbian\sis directory
      This command will create unsigned installation file ruby.sis. To sign it follow the guidlines from www.symbiansigned.com
 
+(4) In case dynamic extensions support was enabled repeat (3) for ruby_core_ext.pkg
+
 == Known problems
 
 Currently gems are not supported.
 Currently signals are supported with reduced functionality (see OpenC release notes.)
+Dynamic extensions could be installed only on internal drive "C".
 
 =end
 
Index: mvm/ext/tk/lib/tk.rb
===================================================================
--- mvm/ext/tk/lib/tk.rb	(revision 26939)
+++ mvm/ext/tk/lib/tk.rb	(revision 26940)
@@ -5663,7 +5663,7 @@
 #Tk.freeze
 
 module Tk
-  RELEASE_DATE = '2009-08-04'.freeze
+  RELEASE_DATE = '2010-02-01'.freeze
 
   autoload :AUTO_PATH,        'tk/variable'
   autoload :TCL_PACKAGE_PATH, 'tk/variable'
Index: mvm/ext/tk/extconf.rb
===================================================================
--- mvm/ext/tk/extconf.rb	(revision 26939)
+++ mvm/ext/tk/extconf.rb	(revision 26940)
@@ -634,7 +634,8 @@
   TkLib_Config["tclConfig-dir"] = tclConfig_dir
   TkLib_Config["tkConfig-dir"] = tkConfig_dir
 
-  print("Search tclConfig.sh and tkConfig.sh in #{tclConfig_dir}.")
+  print("Search tclConfig.sh", (tclConfig_dir)? " (in #{tclConfig_dir})": "", 
+        " and tkConfig.sh", (tkConfig_dir)? " (in #{tkConfig_dir})": "", ".")
   if tclConfig_dir
     tclConfig, tkConfig = 
       search_tclConfig([ ((tclConfig_file)? tclConfig_file: tclConfig_dir), 
@@ -727,7 +728,14 @@
 end
 
 def search_vers_on_path(vers, path, *heads)
-  files = Dir.glob(File.join(path, "*{#{heads.join(',')}}*.{#{CONFIG['LIBEXT']},#{CONFIG['DLEXT']}}"))
+  if enable_config("shared") == false
+    exts = CONFIG['LIBEXT'] + ',' + CONFIG['DLEXT']
+  else
+    exts = CONFIG['DLEXT'] + ',' + CONFIG['LIBEXT']
+  end
+  exts << ",dll,lib" if is_win32?
+  exts << ",bundle,dylib" if is_macosx? || /nextstep|openstep|rhapsody/ =~ RUBY_PLATFORM
+  files = Dir.glob(File.join(path, "*{#{heads.join(',')}}*.{#{exts}}"))
   vers.find_all{|ver| files.find{|f| f =~ /(#{ver}|#{ver.delete('.')})/} }
 end
 
@@ -1256,6 +1264,8 @@
 have_func("rb_obj_taint", "ruby.h")
 print(".") # progress
 have_func("rb_set_safe_level_force", "ruby.h")
+print(".") # progress
+have_func("rb_sourcefile", "ruby.h")
 print("\n") # progress
 
 print("check struct members.")
Index: mvm/ext/tk/tkutil/tkutil.c
===================================================================
--- mvm/ext/tk/tkutil/tkutil.c	(revision 26939)
+++ mvm/ext/tk/tkutil/tkutil.c	(revision 26940)
@@ -7,7 +7,7 @@
 
 ************************************************/
 
-#define TKUTIL_RELEASE_DATE "2009-10-27"
+#define TKUTIL_RELEASE_DATE "2010-02-01"
 
 #include "ruby.h"
 
Index: mvm/ext/nkf/nkf-utf8/nkf.c
===================================================================
--- mvm/ext/nkf/nkf-utf8/nkf.c	(revision 26939)
+++ mvm/ext/nkf/nkf-utf8/nkf.c	(revision 26940)
@@ -20,11 +20,11 @@
  *
  * 3. This notice may not be removed or altered from any source distribution.
  */
-#define NKF_VERSION "2.0.9"
-#define NKF_RELEASE_DATE "2009-01-20"
+#define NKF_VERSION "2.1.1"
+#define NKF_RELEASE_DATE "2010-03-15"
 #define COPY_RIGHT \
     "Copyright (C) 1987, FUJITSU LTD. (I.Ichikawa).\n" \
-    "Copyright (C) 1996-2009, The nkf Project."
+    "Copyright (C) 1996-2010, The nkf Project."
 
 #include "config.h"
 #include "nkf.h"
@@ -210,6 +210,8 @@
 } encoding_name_to_id_table[] = {
     {"US-ASCII",		ASCII},
     {"ASCII",			ASCII},
+    {"646",			ASCII},
+    {"ROMAN8",			ASCII},
     {"ISO-2022-JP",		ISO_2022_JP},
     {"ISO2022JP-CP932",		CP50220},
     {"CP50220",			CP50220},
@@ -221,6 +223,7 @@
     {"ISO-2022-JP-2004",	ISO_2022_JP_2004},
     {"SHIFT_JIS",		SHIFT_JIS},
     {"SJIS",			SHIFT_JIS},
+    {"PCK",			SHIFT_JIS},
     {"WINDOWS-31J",		WINDOWS_31J},
     {"CSWINDOWS31J",		WINDOWS_31J},
     {"CP932",			WINDOWS_31J},
@@ -295,7 +298,7 @@
 			       && (c != '(') && (c != ')') && (c != '.') && (c != 0x22)))
 
 #define is_ibmext_in_sjis(c2) (CP932_TABLE_BEGIN <= c2 && c2 <= CP932_TABLE_END)
-#define nkf_byte_jisx0201_katakana_p(c) (SP <= c && c < (0xE0&0x7F))
+#define nkf_byte_jisx0201_katakana_p(c) (SP <= c && c <= 0x5F)
 
 #define         HOLD_SIZE       1024
 #if defined(INT_IS_SHORT)
@@ -468,6 +471,8 @@
     {"Shift_JIS", 0, 0, 0, {0, 0, 0}, s_status, s_iconv, 0},
 #ifdef UTF8_INPUT_ENABLE
     {"UTF-8",     0, 0, 0, {0, 0, 0}, w_status, w_iconv, 0},
+    {"UTF-16",     0, 0, 0, {0, 0, 0}, NULL, w_iconv16, 0},
+    {"UTF-32",     0, 0, 0, {0, 0, 0}, NULL, w_iconv32, 0},
 #endif
     {0}
 };
@@ -809,7 +814,7 @@
 nkf_buf_new(int length)
 {
     nkf_buf_t *buf = nkf_xmalloc(sizeof(nkf_buf_t));
-    buf->ptr = nkf_xmalloc(length);
+    buf->ptr = nkf_xmalloc(sizeof(nkf_char) * length);
     buf->capa = length;
     buf->len = 0;
     return buf;
@@ -827,7 +832,7 @@
 #define nkf_buf_length(buf) ((buf)->len)
 #define nkf_buf_empty_p(buf) ((buf)->len == 0)
 
-static unsigned char
+static nkf_char
 nkf_buf_at(nkf_buf_t *buf, int index)
 {
     assert(index <= buf->len);
@@ -849,7 +854,7 @@
     buf->ptr[buf->len++] = c;
 }
 
-static unsigned char
+static nkf_char
 nkf_buf_pop(nkf_buf_t *buf)
 {
     assert(!nkf_buf_empty_p(buf));
@@ -1026,7 +1031,7 @@
     int shift = 20;
     c &= VALUE_MASK;
     while(shift >= 0){
-	if(c >= 1<<shift){
+	if(c >= NKF_INT32_C(1)<<shift){
 	    while(shift >= 0){
 		(*f)(0, bin2hex(c>>shift));
 		shift -= 4;
@@ -1204,6 +1209,7 @@
     case CP50220:
     case CP50221:
     case CP50222:
+	x0201_f = TRUE;
 #ifdef SHIFTJIS_CP932
 	cp51932_f = TRUE;
 #endif
@@ -1225,6 +1231,7 @@
     case SHIFT_JIS:
 	break;
     case WINDOWS_31J:
+	x0201_f = TRUE;
 #ifdef SHIFTJIS_CP932
 	cp51932_f = TRUE;
 #endif
@@ -1246,6 +1253,7 @@
     case EUCJP_NKF:
 	break;
     case CP51932:
+	x0201_f = TRUE;
 #ifdef SHIFTJIS_CP932
 	cp51932_f = TRUE;
 #endif
@@ -1325,6 +1333,7 @@
 #endif
 	break;
     case CP50221:
+	x0201_f = TRUE;
 #ifdef SHIFTJIS_CP932
 	if (cp932inv_f == TRUE) cp932inv_f = FALSE;
 #endif
@@ -1332,6 +1341,11 @@
 	ms_ucs_map_f = UCS_MAP_CP932;
 #endif
 	break;
+    case ISO_2022_JP:
+#ifdef SHIFTJIS_CP932
+	if (cp932inv_f == TRUE) cp932inv_f = FALSE;
+#endif
+	break;
     case ISO_2022_JP_1:
 	x0212_f = TRUE;
 #ifdef SHIFTJIS_CP932
@@ -1348,6 +1362,7 @@
     case SHIFT_JIS:
 	break;
     case WINDOWS_31J:
+	x0201_f = TRUE;
 #ifdef UTF8_OUTPUT_ENABLE
 	ms_ucs_map_f = UCS_MAP_CP932;
 #endif
@@ -1376,6 +1391,7 @@
 #endif
 	break;
     case CP51932:
+	x0201_f = TRUE;
 #ifdef SHIFTJIS_CP932
 	if (cp932inv_f == TRUE) cp932inv_f = FALSE;
 #endif
@@ -1426,6 +1442,7 @@
 	output_endian = ENDIAN_LITTLE;
 	output_bom_f = TRUE;
 	break;
+    case UTF_32:
     case UTF_32BE_BOM:
 	output_bom_f = TRUE;
 	break;
@@ -1652,7 +1669,7 @@
 	*p3 = 0x80 | ( val        & 0x3f);
 	*p4 = 0;
     } else if (nkf_char_unicode_value_p(val)) {
-	*p1 = 0xe0 |  (val >> 16);
+	*p1 = 0xf0 |  (val >> 18);
 	*p2 = 0x80 | ((val >> 12) & 0x3f);
 	*p3 = 0x80 | ((val >>  6) & 0x3f);
 	*p4 = 0x80 | ( val        & 0x3f);
@@ -2216,13 +2233,15 @@
 static nkf_char
 w_iconv16(nkf_char c2, nkf_char c1, nkf_char c0)
 {
-    return 0;
+    (*oconv)(c2, c1);
+    return 16; /* different from w_iconv32 */
 }
 
 static nkf_char
 w_iconv32(nkf_char c2, nkf_char c1, nkf_char c0)
 {
-    return 0;
+    (*oconv)(c2, c1);
+    return 32; /* different from w_iconv16 */
 }
 
 static size_t
@@ -3036,24 +3055,24 @@
 }
 #endif /*WIN32DLL*/
 
-static unsigned char   hold_buf[HOLD_SIZE*2];
+static nkf_char   hold_buf[HOLD_SIZE*2];
 static int             hold_count = 0;
 static nkf_char
 push_hold_buf(nkf_char c2)
 {
     if (hold_count >= HOLD_SIZE*2)
 	return (EOF);
-    hold_buf[hold_count++] = (unsigned char)c2;
+    hold_buf[hold_count++] = c2;
     return ((hold_count >= HOLD_SIZE*2) ? EOF : hold_count);
 }
 
 static int
-h_conv(FILE *f, int c1, int c2)
+h_conv(FILE *f, nkf_char c1, nkf_char c2)
 {
-    int ret, c4, c3;
+    int ret;
     int hold_index;
+    nkf_char c3, c4;
 
-
     /** it must NOT be in the kanji shifte sequence      */
     /** it must NOT be written in JIS7                   */
     /** and it must be after 2 byte 8bit code            */
@@ -3102,7 +3121,11 @@
     hold_index = 0;
     while (hold_index < hold_count){
 	c1 = hold_buf[hold_index++];
-	if (c1 <= DEL){
+	if (nkf_char_unicode_p(c1)) {
+	    (*oconv)(0, c1);
+	    continue;
+	}
+	else if (c1 <= DEL){
 	    (*iconv)(0, c1, 0);
 	    continue;
 	}else if (iconv == s_iconv && 0xa1 <= c1 && c1 <= 0xdf){
@@ -3128,18 +3151,16 @@
 	    } else if ((c3 = (*i_getc)(f)) == EOF) {
 		ret = EOF;
 		break;
-	    } else {
-		code_status(c3);
-		if (hold_index < hold_count){
-		    c4 = hold_buf[hold_index++];
-		} else if ((c4 = (*i_getc)(f)) == EOF) {
-		    c3 = ret = EOF;
-		    break;
-		} else {
-		    code_status(c4);
-		    (*iconv)(c1, c2, (c3<<8)|c4);
-		}
 	    }
+	    code_status(c3);
+	    if (hold_index < hold_count){
+		c4 = hold_buf[hold_index++];
+	    } else if ((c4 = (*i_getc)(f)) == EOF) {
+		c3 = ret = EOF;
+		break;
+	    }
+	    code_status(c4);
+	    (*iconv)(c1, c2, (c3<<8)|c4);
 	    break;
 	case -1:
 	    /* 3 bytes EUC or UTF-8 */
@@ -3339,6 +3360,40 @@
     else if (c2 != 0 || c1 != LF) (*o_eol_conv)(c2, c1);
 }
 
+static void
+put_newline(void (*func)(nkf_char))
+{
+    switch (eolmode_f ? eolmode_f : DEFAULT_NEWLINE) {
+      case CRLF:
+	(*func)(0x0D);
+	(*func)(0x0A);
+	break;
+      case CR:
+	(*func)(0x0D);
+	break;
+      case LF:
+	(*func)(0x0A);
+	break;
+    }
+}
+
+static void
+oconv_newline(void (*func)(nkf_char, nkf_char))
+{
+    switch (eolmode_f ? eolmode_f : DEFAULT_NEWLINE) {
+      case CRLF:
+	(*func)(0, 0x0D);
+	(*func)(0, 0x0A);
+	break;
+      case CR:
+	(*func)(0, 0x0D);
+	break;
+      case LF:
+	(*func)(0, 0x0A);
+	break;
+    }
+}
+
 /*
    Return value of fold_conv()
 
@@ -3511,13 +3566,13 @@
     /* terminator process */
     switch(fold_state) {
     case LF:
-	OCONV_NEWLINE((*o_fconv));
+	oconv_newline(o_fconv);
 	(*o_fconv)(c2,c1);
 	break;
     case 0:
 	return;
     case CR:
-	OCONV_NEWLINE((*o_fconv));
+	oconv_newline(o_fconv);
 	break;
     case TAB:
     case SP:
@@ -3804,6 +3859,7 @@
     (const unsigned char *)"\075?ISO-8859-1?Q?",
     (const unsigned char *)"\075?ISO-8859-1?B?",
     (const unsigned char *)"\075?ISO-2022-JP?B?",
+    (const unsigned char *)"\075?ISO-2022-JP?B?",
     (const unsigned char *)"\075?ISO-2022-JP?Q?",
 #if defined(UTF8_INPUT_ENABLE)
     (const unsigned char *)"\075?UTF-8?B?",
@@ -3824,7 +3880,7 @@
 };
 
 static const nkf_char mime_encode[] = {
-    EUC_JP, SHIFT_JIS, ISO_8859_1, ISO_8859_1, JIS_X_0208, JIS_X_0201_1976_K,
+    EUC_JP, SHIFT_JIS, ISO_8859_1, ISO_8859_1, JIS_X_0208, JIS_X_0201_1976_K, JIS_X_0201_1976_K,
 #if defined(UTF8_INPUT_ENABLE)
     UTF_8, UTF_8,
 #endif
@@ -3833,7 +3889,7 @@
 };
 
 static const nkf_char mime_encode_method[] = {
-    'B', 'B','Q', 'B', 'B', 'Q',
+    'B', 'B','Q', 'B', 'B', 'B', 'Q',
 #if defined(UTF8_INPUT_ENABLE)
     'B', 'Q',
 #endif
@@ -4427,7 +4483,7 @@
 	}
 	if (c1=='='&&c2<SP) { /* this is soft wrap */
 	    while((c1 =  (*i_mgetc)(f)) <=SP) {
-		if ((c1 = (*i_mgetc)(f)) == EOF) return (EOF);
+		if (c1 == EOF) return (EOF);
 	    }
 	    mime_decode_mode = 'Q'; /* still in MIME */
 	    goto restart_mime_q;
@@ -4599,7 +4655,7 @@
 	    (*o_mputc)(mimeout_state.buf[i]);
 	    i++;
 	}
-	PUT_NEWLINE((*o_mputc));
+	put_newline(o_mputc);
 	(*o_mputc)(SP);
 	base64_count = 1;
 	if (mimeout_state.count>0 && nkf_isspace(mimeout_state.buf[i])) {
@@ -4632,14 +4688,14 @@
 	if (c2 == EOF){
 	    if (base64_count + mimeout_state.count/3*4> 73){
 		(*o_base64conv)(EOF,0);
-		OCONV_NEWLINE((*o_base64conv));
+		oconv_newline(o_base64conv);
 		(*o_base64conv)(0,SP);
 		base64_count = 1;
 	    }
 	} else {
-	    if (base64_count + mimeout_state.count/3*4> 66) {
+	    if ((c2 != 0 || c1 > DEL) && base64_count + mimeout_state.count/3*4> 66) {
 		(*o_base64conv)(EOF,0);
-		OCONV_NEWLINE((*o_base64conv));
+		oconv_newline(o_base64conv);
 		(*o_base64conv)(0,SP);
 		base64_count = 1;
 		mimeout_mode = -1;
@@ -4650,7 +4706,7 @@
 	    mimeout_mode =  (output_mode==ASCII ||output_mode == ISO_8859_1) ? 'Q' : 'B';
 	    open_mime(output_mode);
 	    (*o_base64conv)(EOF,0);
-	    OCONV_NEWLINE((*o_base64conv));
+	    oconv_newline(o_base64conv);
 	    (*o_base64conv)(0,SP);
 	    base64_count = 1;
 	    mimeout_mode = -1;
@@ -4748,14 +4804,14 @@
 	    if (base64_count > 71){
 		if (c!=CR && c!=LF) {
 		    (*o_mputc)('=');
-		    PUT_NEWLINE((*o_mputc));
+		    put_newline(o_mputc);
 		}
 		base64_count = 0;
 	    }
 	}else{
 	    if (base64_count > 71){
 		eof_mime();
-		PUT_NEWLINE((*o_mputc));
+		put_newline(o_mputc);
 		base64_count = 0;
 	    }
 	    if (c == EOF) { /* c==EOF */
@@ -4817,7 +4873,7 @@
 	    } else if (c <= SP) {
 		close_mime();
 		if (base64_count > 70) {
-		    PUT_NEWLINE((*o_mputc));
+		    put_newline(o_mputc);
 		    base64_count = 0;
 		}
 		if (!nkf_isblank(c)) {
@@ -4827,7 +4883,7 @@
 	    } else {
 		if (base64_count > 70) {
 		    close_mime();
-		    PUT_NEWLINE((*o_mputc));
+		    put_newline(o_mputc);
 		    (*o_mputc)(SP);
 		    base64_count = 1;
 		    open_mime(output_mode);
@@ -4837,14 +4893,17 @@
 		    return;
 		}
 	    }
-	    (*o_mputc)(c);
-	    base64_count++;
+	    if (c != 0x1B) {
+		(*o_mputc)(c);
+		base64_count++;
+		return;
+	    }
 	}
-	return;
     }
 
     if (mimeout_mode <= 0) {
-	if (c <= DEL && (output_mode==ASCII ||output_mode == ISO_8859_1)) {
+	if (c <= DEL && (output_mode==ASCII || output_mode == ISO_8859_1 ||
+		    output_mode == UTF_8)) {
 	    if (nkf_isspace(c)) {
 		int flag = 0;
 		if (mimeout_mode == -1) {
@@ -4889,7 +4948,7 @@
 		    }
 
 		    if (i == 0 || i == mimeout_state.count - len) {
-			PUT_NEWLINE((*o_mputc));
+			put_newline(o_mputc);
 			base64_count = 0;
 			if (!nkf_isspace(mimeout_state.buf[0])){
 			    (*o_mputc)(SP);
@@ -4901,7 +4960,7 @@
 			for (j = 0; j <= i; ++j) {
 			    (*o_mputc)(mimeout_state.buf[j]);
 			}
-			PUT_NEWLINE((*o_mputc));
+			put_newline(o_mputc);
 			base64_count = 1;
 			for (; j <= mimeout_state.count; ++j) {
 			    mimeout_state.buf[j - i] = mimeout_state.buf[j];
@@ -4935,14 +4994,15 @@
 	}
     }else{
 	/* mimeout_mode == 'B', 1, 2 */
-	if ( c<=DEL && (output_mode==ASCII ||output_mode == ISO_8859_1)) {
+	if (c <= DEL && (output_mode==ASCII || output_mode == ISO_8859_1 ||
+		    output_mode == UTF_8)) {
 	    if (lastchar == CR || lastchar == LF){
 		if (nkf_isblank(c)) {
 		    for (i=0;i<mimeout_state.count;i++) {
 			mimeout_addchar(mimeout_state.buf[i]);
 		    }
 		    mimeout_state.count = 0;
-		} else if (SP<c && c<DEL) {
+		} else {
 		    eof_mime();
 		    for (i=0;i<mimeout_state.count;i++) {
 			(*o_mputc)(mimeout_state.buf[i]);
@@ -5238,6 +5298,8 @@
     set_output_encoding(output_encoding);
     oconv = nkf_enc_to_oconv(output_encoding);
     o_putc = std_putc;
+    if (nkf_enc_unicode_p(output_encoding))
+	output_mode = UTF_8;
 
     /* replace continucation module, from output side */
 
@@ -5386,7 +5448,7 @@
 	       (c4 = (*i_getc)(f)) != EOF) {
 	    nkf_iconv_utf_32(c1, c2, c3, c4);
 	}
-	(*i_ungetc)(EOF, f);
+	goto finished;
     }
     else if (iconv == w_iconv16) {
 	while ((c1 = (*i_getc)(f)) != EOF &&
@@ -5397,7 +5459,7 @@
 		nkf_iconv_utf_16(c1, c2, c3, c4);
 	    }
 	}
-	(*i_ungetc)(EOF, f);
+	goto finished;
     }
 #endif
 
@@ -5444,6 +5506,12 @@
 	    if (input_mode == JIS_X_0208 && DEL <= c1 && c1 < 0x92) {
 		/* CP5022x */
 		MORE;
+	    }else if (input_codename && input_codename[0] == 'I' &&
+		    0xA1 <= c1 && c1 <= 0xDF) {
+		/* JIS X 0201 Katakana in 8bit JIS */
+		c2 = JIS_X_0201_1976_K;
+		c1 &= 0x7f;
+		SEND;
 	    } else if (c1 > DEL) {
 		/* 8 bit code */
 		if (!estab_f && !iso8859_f) {
@@ -5518,7 +5586,7 @@
 		SKIP;
 	    } else if (c1 == ESC && (!is_8bit || mime_decode_mode)) {
 		if ((c1 = (*i_getc)(f)) == EOF) {
-		    /*  (*oconv)(0, ESC); don't send bogus code */
+		    (*oconv)(0, ESC);
 		    LAST;
 		}
 		else if (c1 == '&') {
@@ -5648,7 +5716,7 @@
 	    } else if (c1 == ESC && iconv == s_iconv) {
 		/* ESC in Shift_JIS */
 		if ((c1 = (*i_getc)(f)) == EOF) {
-		    /*  (*oconv)(0, ESC); don't send bogus code */
+		    (*oconv)(0, ESC);
 		    LAST;
 		} else if (c1 == '$') {
 		    /* J-PHONE emoji */
@@ -5773,6 +5841,7 @@
 	/* goto next_word */
     }
 
+finished:
     /* epilogue */
     (*iconv)(EOF, 0, 0);
     if (!input_codename)
@@ -6132,7 +6201,7 @@
 	    break;
 #endif
 #ifdef UTF8_OUTPUT_ENABLE
-	case 'w':           /* UTF-8 output */
+	case 'w':           /* UTF-{8,16,32} output */
 	    if (cp[0] == '8') {
 		cp++;
 		if (cp[0] == '0'){
@@ -6157,19 +6226,18 @@
 		if (cp[0]=='L') {
 		    cp++;
 		    output_endian = ENDIAN_LITTLE;
+		    output_bom_f = TRUE;
 		} else if (cp[0] == 'B') {
 		    cp++;
-		} else {
-		    output_encoding = nkf_enc_from_index(enc_idx);
-		    continue;
+		    output_bom_f = TRUE;
 		}
 		if (cp[0] == '0'){
+		    output_bom_f = FALSE;
 		    cp++;
 		    enc_idx = enc_idx == UTF_16
 			? (output_endian == ENDIAN_LITTLE ? UTF_16LE : UTF_16BE)
 			: (output_endian == ENDIAN_LITTLE ? UTF_32LE : UTF_32BE);
 		} else {
-		    output_bom_f = TRUE;
 		    enc_idx = enc_idx == UTF_16
 			? (output_endian == ENDIAN_LITTLE ? UTF_16LE_BOM : UTF_16BE_BOM)
 			: (output_endian == ENDIAN_LITTLE ? UTF_32LE_BOM : UTF_32BE_BOM);
@@ -6229,10 +6297,10 @@
 	       bit:3   Convert HTML Entity
 	       bit:4   Convert JIS X 0208 Katakana to JIS X 0201 Katakana
 	     */
-	    while ('0'<= *cp && *cp <='9') {
+	    while ('0'<= *cp && *cp <='4') {
 		alpha_f |= 1 << (*cp++ - '0');
 	    }
-	    if (!alpha_f) alpha_f = 1;
+	    alpha_f |= 1;
 	    continue;
 	case 'x':   /* Convert X0201 kana to X0208 or X0201 Conversion */
 	    x0201_f = FALSE;    /* No X0201->X0208 conversion */
Index: mvm/NEWS
===================================================================
--- mvm/NEWS	(revision 26939)
+++ mvm/NEWS	(revision 26940)
@@ -27,6 +27,13 @@
     * new encodings:
       * Big5
       * Big5-UAO
+      * ISO-2022-JP-KDDI
+      * SJIS-DoCoMo
+      * SJIS-KDDI
+      * SJIS-SoftBank
+      * UTF8-DoCoMo
+      * UTF8-KDDI
+      * UTF8-SoftBank
 
     * new method:
       * ascii_compatible?
Index: mvm/.merged-trunk-revision
===================================================================
--- mvm/.merged-trunk-revision	(revision 26939)
+++ mvm/.merged-trunk-revision	(revision 26940)
@@ -1 +1 @@
-26885
+26939
Index: mvm/version.h
===================================================================
--- mvm/version.h	(revision 26939)
+++ mvm/version.h	(revision 26940)
@@ -1,5 +1,5 @@
 #define RUBY_VERSION "1.9.2"
-#define RUBY_RELEASE_DATE "2010-03-12"
+#define RUBY_RELEASE_DATE "2010-03-15"
 #define RUBY_PATCHLEVEL -1
 #define RUBY_BRANCH_NAME "mvm"
 
@@ -8,7 +8,7 @@
 #define RUBY_VERSION_TEENY 1
 #define RUBY_RELEASE_YEAR 2010
 #define RUBY_RELEASE_MONTH 3
-#define RUBY_RELEASE_DAY 12
+#define RUBY_RELEASE_DAY 15
 
 #include "ruby/version.h"
 
Index: mvm/ruby.c
===================================================================
--- mvm/ruby.c	(revision 26939)
+++ mvm/ruby.c	(revision 26940)
@@ -337,6 +337,7 @@
 ruby_init_loadpath_safe(int safe_level)
 {
     VALUE load_path;
+    ID id_initial_load_path_mark;
     extern const char ruby_initial_load_paths[];
     const char *paths = ruby_initial_load_paths;
 #if defined LOAD_RELATIVE
@@ -430,16 +431,18 @@
 #define RUBY_RELATIVE(path, len) rubylib_mangled_path(path, len)
 #define PREFIX_PATH() rubylib_mangled_path(RUBY_LIB_PREFIX, sizeof(RUBY_LIB_PREFIX)-1)
 #endif
-#define incpush(path) rb_ary_push(load_path, (path))
     load_path = GET_VM()->load_path;
 
     if (safe_level == 0) {
 	ruby_push_include(getenv("RUBYLIB"), identical_path);
     }
 
+    id_initial_load_path_mark = rb_intern_const("@gem_prelude_index");
     while (*paths) {
 	size_t len = strlen(paths);
-	incpush(RUBY_RELATIVE(paths, len));
+	VALUE path = RUBY_RELATIVE(paths, len);
+	rb_ivar_set(path, id_initial_load_path_mark, path);
+	rb_ary_push(load_path, path);
 	paths += len + 1;
     }
 
Index: mvm/tool/transcode-tblgen.rb
===================================================================
--- mvm/tool/transcode-tblgen.rb	(revision 26939)
+++ mvm/tool/transcode-tblgen.rb	(revision 26940)
@@ -1,7 +1,24 @@
 require 'optparse'
 require 'erb'
 require 'fileutils'
+require 'pp'
 
+class Array
+  unless [].respond_to? :product
+    def product(*args)
+      if args.empty?
+        self.map {|e| [e] }
+      else
+        result = []
+        self.each {|e0|
+          result.concat args.first.product(*args[1..-1]).map {|es| [e0, *es] }
+        }
+        result
+      end
+    end
+  end
+end
+
 NUM_ELEM_BYTELOOKUP = 2
 
 C_ESC = {
@@ -18,257 +35,287 @@
   '"' + str.gsub(C_ESC_PAT) { C_ESC[$&] } + '"'
 end
 
-HEX2 = /[0-9A-Fa-f]{2}/
+HEX2 = /(?:[0-9A-Fa-f]{2})/
 
-class StrSet
-  attr_reader :pat
+class ArrayCode
+  def initialize(type, name)
+    @type = type
+    @name = name
+    @len = 0;
+    @content = ''
+  end
 
-  SINGLE_BYTE_RANGES = (0..255).map {|i| [i..i] }
+  def length
+    @len
+  end
 
-  def self.parse(pattern)
-    if /\A\s*((#{HEX2}|\{(#{HEX2}|#{HEX2}-#{HEX2})(,(#{HEX2}|#{HEX2}-#{HEX2}))*\})+(\s+|\z))*\z/o !~ pattern
-      raise ArgumentError, "invalid pattern: #{pattern.inspect}"
-    end
-    result = []
-    pattern.scan(/\S+/) {|seq|
-      seq_result = []
-      while !seq.empty?
-        if /\A(#{HEX2})/o =~ seq
-          byte = $1.to_i(16)
-          seq_result << SINGLE_BYTE_RANGES[byte]
-          seq = $'
-        elsif /\A\{([^\}]+)\}/ =~ seq
-          set = $1
-          seq = $'
-          set_result = []
-          set.scan(/[^,]+/) {|range|
-            if /\A(#{HEX2})-(#{HEX2})\z/o =~ range
-              b = $1.to_i(16)
-              e = $2.to_i(16)
-              set_result << (b..e)
-            elsif /\A(#{HEX2})\z/o =~ range
-              byte = $1.to_i(16)
-              set_result << (byte..byte)
-            else
-              raise "invalid range: #{range.inspect}"
-            end
-          }
-          seq_result << set_result
-        else
-          raise "invalid sequence: #{seq.inspect}"
-        end
-      end
-      result << seq_result
-    }
-    self.new(result)
+  def insert_at_last(num, str)
+    newnum = self.length + num
+    @content << str
+    @len += num
   end
 
-  def initialize(pat)
-    @pat = pat
+  def to_s
+    <<"End"
+static const #{@type}
+#{@name}[#{@len}] = {
+#{@content}};
+End
   end
+end
 
+class Action
+  def initialize(value)
+    @value = value
+  end
+  attr_reader :value
+
   def hash
-    return @hash if defined? @hash
-    @hash = @pat.hash
+    @value.hash
   end
 
   def eql?(other)
     self.class == other.class &&
-    @pat == other.pat
+    @value == other.value
   end
-
   alias == eql?
+end
 
-  def to_s
-    if @pat.empty?
-      "(empset)"
-    else
-      @pat.map {|seq|
-        if seq.empty?
-          "(empstr)"
-        else
-          seq.map {|byteset|
-            if byteset.length == 1 && byteset[0].begin == byteset[0].end
-              "%02x" % byteset[0].begin
+class ActionMap
+  def self.parse_to_rects(hash)
+    h = {}
+    hash.each {|pat, action|
+      pat = pat.to_s
+      h[pat] = action
+    }
+    hash = h
+
+    rects = []
+    n = 0
+    hash.each {|pat, action|
+      if /\A\s*\(empset\)\s*\z/ =~ pat
+        next
+      elsif /\A\s*\(empstr\)\s*\z/ =~ pat
+        rects << ['', '', action]
+        n += 1
+      elsif /\A\s*(#{HEX2}+)\s*\z/o =~ pat
+        hex = $1.upcase
+        rects << [hex, hex, action]
+      elsif /\A\s*((#{HEX2}|\{#{HEX2}(?:-#{HEX2})?(,#{HEX2}(?:-#{HEX2})?)*\})+(\s+|\z))*\z/o =~ pat
+        pat = pat.upcase
+        pat.scan(/\S+/) {
+          pat1 = $&
+          ranges_list = []
+          pat1.scan(/#{HEX2}|\{([^\}]*)\}/o) {
+            ranges_list << []
+            if !$1
+              ranges_list.last << [$&,$&]
             else
-              "{" + 
-              byteset.map {|range|
-                if range.begin == range.end
-                  "%02x" % range.begin
+              set = {}
+              $1.scan(/(#{HEX2})(?:-(#{HEX2}))?/o) {
+                if !$2
+                  c = $1.to_i(16)
+                  set[c] = true
                 else
-                  "%02x-%02x" % [range.begin, range.end]
+                  b = $1.to_i(16)
+                  e = $2.to_i(16)
+                  b.upto(e) {|c| set[c] = true }
                 end
-              }.join(',') +
-              "}"
+              }
+              i = nil
+              0.upto(256) {|j|
+                if set[j]
+                  if !i
+                    i = j
+                  end
+                  if !set[j+1]
+                    ranges_list.last << ["%02X" % i, "%02X" % j]
+                    i = nil
+                  end
+                end
+              }
             end
-          }.join('')
-        end
-      }.join(' ')
-    end
+          }
+          first_ranges = ranges_list.shift
+          first_ranges.product(*ranges_list).each {|range_list|
+            min = range_list.map {|x, y| x }.join
+            max = range_list.map {|x, y| y }.join
+            rects << [min, max, action]
+          }
+        }
+      else
+        raise ArgumentError, "invalid pattern: #{pat.inspect}"
+      end
+    }
+    rects
   end
 
-  def inspect
-    "\#<#{self.class}: #{self.to_s}>"
-  end
-
-  def min_length
-    if @pat.empty?
-      nil
+  def self.unambiguous_action(actions0)
+    actions = actions0.uniq
+    if actions.length == 1
+      actions[0]
     else
-      @pat.map {|seq| seq.length }.min
+      actions = actions.find_all {|action| action != :nomap0 }
+      if actions.length == 1
+        actions[0]
+      else
+        raise ArgumentError, "ambiguous actions: #{actions0.inspect}"
+      end
     end
   end
 
-  def max_length
-    if @pat.empty?
-      nil
-    else
-      @pat.map {|seq| seq.length }.max
-    end
+  def self.build_tree(rects)
+    expand("", rects) {|actions|
+      unambiguous_action(actions)
+    }
   end
 
-  def emptyable?
-    @pat.any? {|seq|
-      seq.empty?
-    }
+  def self.parse(hash)
+    rects = parse_to_rects(hash)
+    tree = build_tree(rects)
+    self.new("", tree)
   end
 
-  def first_bytes
-    result = {}
-    @pat.each {|seq|
-      next if seq.empty?
-      seq.first.each {|range|
-        range.each {|byte|
-          result[byte] = true
-        }
-      }
+  def self.merge(*rects_list)
+    if rects_list.length < 2
+      raise ArgumentError, "not enough arguments"
+    end
+
+    all_rects = []
+    rects_list.each_with_index {|rects, i|
+      all_rects.concat rects.map {|min, max, action| [min, max, [i, action]] }
     }
-    result.keys.sort
-  end
 
-  def each_firstbyte
-    h = {}
-    @pat.each {|seq|
-      next if seq.empty?
-      seq.first.each {|range|
-        range.each {|byte|
-          (h[byte] ||= []) << seq[1..-1]
-        }
+    tree = expand("", all_rects) {|actions|
+      args = Array.new(rects_list.length) { [] }
+      actions.each {|i, action|
+        args[i] << action
       }
+      yield(args)
     }
-    h.keys.sort.each {|byte|
-      yield byte, StrSet.new(h[byte])
-    }
-  end
-end
 
-class ArrayCode
-  def initialize(type, name)
-    @type = type
-    @name = name
-    @len = 0;
-    @content = ''
+    self.new("", tree)
   end
 
-  def length
-    @len
+  def self.expand(prefix, rects, &block)
+    return [] if rects.empty?
+    has_empty = false
+    has_nonempty = false
+    rects.each {|min, max, action|
+      if min.empty?
+        has_empty = true
+      else
+        has_nonempty = true
+      end
+    }
+    if has_empty && has_nonempty
+      raise ArgumentError, "ambiguous pattern: #{prefix}"
+    end
+    if has_empty
+      actions = rects.map {|min, max, action| action }.uniq
+      act = block.call(actions)
+      tree = Action.new(act)
+    else
+      tree = []
+      each_firstbyte_range(prefix, rects) {|byte_min, byte_max, rects2|
+        prefix2 = prefix
+        if byte_min == byte_max
+          prefix2 += "%02X" % byte_min
+        else
+          prefix2 += "{%02X-%02X}" % [byte_min, byte_max]
+        end
+        child_tree = expand(prefix2, rects2, &block)
+        tree << [byte_min, byte_max, child_tree]
+      }
+    end
+    return tree
   end
 
-  def insert_at_last(num, str)
-    newnum = self.length + num
-    @content << str
-    @len += num
-  end
-
-  def to_s
-    <<"End"
-static const #{@type}
-#{@name}[#{@len}] = {
-#{@content}};
-End
-  end
-end
-
-class ActionMap
-  def self.parse(hash)
-    h = {}
-    hash.each {|pat, action|
-      h[StrSet.parse(pat)] = action
+  def self.each_firstbyte_range(prefix, rects)
+    a = []
+    index_from = {}
+    rects.each {|min, max, action|
+      raise ArgumentError, "emptyable pattern" if min.empty?
+      min_firstbyte = min[0,2].to_i(16)
+      min_rest = min[2..-1]
+      max_firstbyte = max[0,2].to_i(16)
+      max_rest = max[2..-1]
+      a << [min_firstbyte, max_firstbyte, [min_rest, max_rest, action]]
+      index_from[min_firstbyte] = true
+      index_from[max_firstbyte+1] = true
     }
-    self.new(h)
+    byte_from = {}
+    index_from.keys.sort.each_with_index {|byte, i|
+      index_from[byte] = i
+      byte_from[i] = byte
+    }
+    rects_hash = {}
+    a.each {|min_firstbyte, max_firstbyte, rest_elt|
+      index_from[min_firstbyte].upto(index_from[max_firstbyte+1]-1) {|i|
+        rects_hash[i] ||= []
+        rects_hash[i] << rest_elt
+      }
+    }
+    0.upto(index_from.size-1) {|i|
+      rects2 = rects_hash[i]
+      yield byte_from[i], byte_from[i+1]-1, rects2 if rects2
+    }
   end
 
-  def initialize(h)
-    @map = h
+  def initialize(prefix, tree)
+    @prefix = prefix # just for debug
+    @tree = tree
   end
 
   def hash
     return @hash if defined? @hash
-    hash = 0
-    @map.each {|k,v|
-      hash ^= k.hash ^ v.hash
-    }
-    @hash = hash
+    @hash = @tree.hash
   end
 
   def eql?(other)
     self.class == other.class &&
-    @map == other.instance_eval { @map }
+    @tree == other.instance_eval { @tree }
   end
 
   alias == eql?
 
   def inspect
     "\#<#{self.class}:" + 
-    @map.map {|k, v| " [" + k.to_s + "]=>" + v.inspect }.join('') +
+    @tree.inspect +
     ">"
   end
 
+  def max_input_length_rec(tree)
+    case tree
+    when Action
+      0
+    else
+      tree.map {|byte_min, byte_max, child_tree|
+        max_input_length_rec(child_tree)
+      }.max + 1
+    end
+  end
+
   def max_input_length
-    @map.keys.map {|k| k.max_length }.max
+    max_input_length_rec(@tree)
   end
 
   def empty_action
-    @map.each {|ss, action|
-      return action if ss.emptyable?
-    }
-    nil
+    if @tree.kind_of? Action
+      @tree.value
+    else
+      nil
+    end
   end
 
-  def each_firstbyte(valid_encoding=nil)
-    h = {}
-    @map.each {|ss, action|
-      if ss.emptyable?
-        raise "emptyable pattern"
-      else
-        ss.each_firstbyte {|byte, rest|
-          h[byte] ||= {}
-          if h[byte][rest].nil?
-          elsif action == :nomap0
-            next
-          elsif h[byte][rest] != :nomap0
-            raise "ambiguous %s or %s (%02X/%s)" % [h[byte][rest], action, byte, rest]
-          end
-          h[byte][rest] = action
-        }
-      end
+  def each_firstbyte
+    @tree.each {|byte_min, byte_max, child_tree|
+      byte_min.upto(byte_max) {|byte|
+        prefix = @prefix + ("%02X" % byte)
+        am = ActionMap.new(prefix, child_tree)
+        yield byte, am
+      }
     }
-    if valid_encoding
-      valid_encoding.each_firstbyte {|byte, rest|
-        if h[byte]
-          am = ActionMap.new(h[byte])
-          yield byte, am, rest
-        else
-          am = ActionMap.new(rest => :undef)
-          yield byte, am, nil
-        end
-      }
-    else
-      h.keys.sort.each {|byte|
-        am = ActionMap.new(h[byte])
-        yield byte, am, nil
-      }
-    end
   end
 
   OffsetsMemo = {}
@@ -433,24 +480,24 @@
   PostMemo = {}
   NextName = "a"
 
-  def generate_node(bytes_code, words_code, name_hint=nil, valid_encoding=nil)
-    if n = PreMemo[[self,valid_encoding]]
+  def generate_node(bytes_code, words_code, name_hint=nil)
+    if n = PreMemo[self]
       return n
     end
 
     table = Array.new(0x100, :invalid)
-    each_firstbyte(valid_encoding) {|byte, rest, rest_valid_encoding|
+    each_firstbyte {|byte, rest|
       if a = rest.empty_action
         table[byte] = a
       else
         name_hint2 = nil
         name_hint2 = "#{name_hint}_#{'%02X' % byte}" if name_hint
-        table[byte] = "/*BYTE_LOOKUP*/" + rest.gennode(bytes_code, words_code, name_hint2, rest_valid_encoding)
+        table[byte] = "/*BYTE_LOOKUP*/" + rest.gennode(bytes_code, words_code, name_hint2)
       end
     }
 
     if n = PostMemo[table]
-      return PreMemo[[self,valid_encoding]] = n
+      return PreMemo[self] = n
     end
 
     if !name_hint
@@ -458,16 +505,16 @@
       NextName.succ!
     end
 
-    PreMemo[[self,valid_encoding]] = PostMemo[table] = name_hint
+    PreMemo[self] = PostMemo[table] = name_hint
 
     generate_lookup_node(bytes_code, words_code, name_hint, table)
     name_hint
   end
 
-  def gennode(bytes_code, words_code, name_hint=nil, valid_encoding=nil)
+  def gennode(bytes_code, words_code, name_hint=nil)
     @bytes_code = bytes_code
     @words_code = words_code
-    name = generate_node(bytes_code, words_code, name_hint, valid_encoding)
+    name = generate_node(bytes_code, words_code, name_hint)
     @bytes_code = nil
     @words_code = nil
     return name
@@ -608,17 +655,20 @@
   map.each {|k, v|
     h[k] = v unless h[k] # use first mapping
   }
-  am = ActionMap.parse(h)
-
-  max_input = am.max_input_length
-
-  if ValidEncoding[from]
-    valid_encoding = StrSet.parse(ValidEncoding[from])
+  if valid_encoding = ValidEncoding[from]
+    rects = ActionMap.parse_to_rects(h)
+    undef_rects = ActionMap.parse_to_rects(valid_encoding => :undef)
+    am = ActionMap.merge(rects, undef_rects) {|a1, a2|
+      a1 = a1.empty? ? nil : ActionMap.unambiguous_action(a1)
+      a2 = a2.empty? ? nil : ActionMap.unambiguous_action(a2)
+      a1 || a2
+    }
   else
-    valid_encoding = nil
+    am = ActionMap.parse(h)
   end
 
-  defined_name = am.gennode(TRANSCODE_GENERATED_BYTES_CODE, TRANSCODE_GENERATED_WORDS_CODE, name, valid_encoding)
+  max_input = am.max_input_length
+  defined_name = am.gennode(TRANSCODE_GENERATED_BYTES_CODE, TRANSCODE_GENERATED_WORDS_CODE, name)
   return defined_name, max_input
 end
 
@@ -773,6 +823,8 @@
 end
 
 if __FILE__ == $0
+  start_time = Time.now
+
   output_filename = nil
   verbose_mode = false
   force_mode = false
@@ -861,7 +913,9 @@
     FileUtils.mkdir_p(File.dirname(output_filename))
     File.open(new_filename, "wb") {|f| f << result }
     File.rename(new_filename, output_filename)
-    STDERR.puts "done." if VERBOSE_MODE
+    tms = Process.times
+    elapsed = Time.now - start_time
+    STDERR.puts "done.  (#{'%.2f' % tms.utime}user #{'%.2f' % tms.stime}system #{'%.2f' % elapsed}elapsed)" if VERBOSE_MODE
   else
     print result
   end
Index: mvm/tool/compile_prelude.rb
===================================================================
--- mvm/tool/compile_prelude.rb	(revision 26939)
+++ mvm/tool/compile_prelude.rb	(revision 26940)
@@ -48,7 +48,7 @@
         key = $1
         unless @mkconf
           require './rbconfig'
-          @mkconf = RbConfig::MAKEFILE_CONFIG.merge('rubylibprefix'=>'#{TMP_RUBY_PREFIX}')
+          @mkconf = RbConfig::MAKEFILE_CONFIG.merge('prefix'=>'#{TMP_RUBY_PREFIX}')
         end
         if RbConfig::MAKEFILE_CONFIG.has_key? key
           val = RbConfig.expand("$(#{key})", @mkconf)
Index: mvm/tool/file2lastrev.rb
===================================================================
--- mvm/tool/file2lastrev.rb	(revision 26939)
+++ mvm/tool/file2lastrev.rb	(revision 26940)
@@ -5,47 +5,77 @@
 require 'optparse'
 require 'pathname'
 
-SRCDIR = Pathname(File.dirname($0)).parent.freeze
-class VCSNotFoundError < RuntimeError; end
+Program = Pathname($0)
 
-def detect_vcs(path)
-  path = SRCDIR
-  return :svn, path.relative_path_from(SRCDIR) if File.directory?("#{path}/.svn")
-  return :git_svn, path.relative_path_from(SRCDIR) if File.directory?("#{path}/.git/svn")
-  return :git, path.relative_path_from(SRCDIR) if File.directory?("#{path}/.git")
-  raise VCSNotFoundError, "does not seem to be under a vcs"
-end
+class VCS
+  class NotFoundError < RuntimeError; end
 
-# return a pair of strings, the last revision and the last revision in which
-# +path+ was modified.
-def get_revisions(path)
-  vcs, path = detect_vcs(path)
+  @@dirs = []
+  def self.register(dir)
+    @@dirs << [dir, self]
+  end
 
-  info = case vcs
-  when :svn
-    info_xml = `cd "#{SRCDIR}" && svn info --xml "#{path}"`
-    _, last, _, changed, _ = info_xml.split(/revision="(\d+)"/)
+  def self.detect(path)
+    @@dirs.sort.reverse_each do |dir, klass|
+      return klass.new(path) if File.directory?("#{path}/#{dir}")
+    end
+    raise VCS::NotFoundError, "does not seem to be under a vcs: #{path}"
+  end
+
+  def initialize(path)
+    @srcdir = path
+  end
+
+  # return a pair of strings, the last revision and the last revision in which
+  # +path+ was modified.
+  def get_revisions(path)
+    path = relative_to(path)
+    last, changed = Dir.chdir(@srcdir) {yield path}
+    last or raise "last revision not found"
+    changed or raise "changed revision not found"
     return last, changed
-  when :git_svn
-    `cd "#{SRCDIR}" && git svn info "#{path}"`
-  when :git
-    git_log = `cd "#{SRCDIR}" && git log HEAD~1..HEAD "#{path}"`
-    git_log =~ /git-svn-id: .*?@(\d+)/
-    return $1, $1
   end
 
-  if /^Revision: (\d+)/ =~ info
-    last = $1 
-  else
-    raise "last revision not found"
+  def relative_to(path)
+    path ? Pathname(path).relative_path_from(@srcdir) : '.'
   end
-  if /^Last Changed Rev: (\d+)/ =~ info
-    changed = $1
-  else
-    raise "changed revision not found"
+
+  class SVN < self
+    register(".svn")
+
+    def get_revisions(*)
+      super do |path|
+        info_xml = `svn info --xml "#{path}"`
+        _, last, _, changed, _ = info_xml.split(/revision="(\d+)"/)
+        [last, changed]
+      end
+    end
   end
 
-  return last, changed
+  class GIT_SVN < self
+    register(".git/svn")
+
+    def get_revisions(*)
+      super do |path|
+        info = `git svn info "#{path}"`
+        [info[/^Revision: (\d+)/, 1], info[/^Last Changed Rev: (\d+)/, 1]]
+      end
+    end
+  end
+
+  class GIT < self
+    register(".git")
+
+    def get_revisions(*)
+      logcmd = %Q[git log -n1 --grep="^ *git-svn-id: .*@[0-9][0-9]* "]
+      idpat = /git-svn-id: .*?@(\d+) \S+\Z/
+      super do |path|
+        last = `#{logcmd}`[idpat, 1]
+        changed = path ? `#{logcmd} "#{path}"`[idpat, 1] : last
+        [last, changed]
+      end
+    end
+  end
 end
 
 @output = nil
@@ -57,27 +87,33 @@
 end
 @suppress_not_found = false
 
+srcdir = nil
 parser = OptionParser.new {|opts|
+  opts.on("--srcdir=PATH", "use PATH as source directory") do |path|
+    srcdir = path
+  end
   opts.on("--changed", "changed rev") do
     self.output = :changed
   end
-  opts.on("--revision.h") do
+  opts.on("--revision.h", "RUBY_REVISION macro") do
     self.output = :revision_h
   end
-  opts.on("--doxygen") do
+  opts.on("--doxygen", "Doxygen format") do
     self.output = :doxygen
   end
   opts.on("-q", "--suppress_not_found") do
     @suppress_not_found = true
   end
 }
-parser.parse!
+parser.parse! rescue abort "#{Program.basename}: #{$!}\n#{parser}"
 
-
+srcdir = (srcdir ? Pathname(srcdir) : Program.parent.parent).freeze
 begin
-  last, changed = get_revisions(ARGV.shift)
-rescue VCSNotFoundError
-  raise unless @suppress_not_found
+  vcs = VCS.detect(srcdir)
+rescue VCS::NotFoundError => e
+  abort "#{Program.basename}: #{e.message}" unless @suppress_not_found
+else
+  last, changed = vcs.get_revisions(ARGV.shift)
 end
 
 case @output
Index: mvm/test/ruby/test_array.rb
===================================================================
--- mvm/test/ruby/test_array.rb	(revision 26939)
+++ mvm/test/ruby/test_array.rb	(revision 26940)
@@ -1565,7 +1565,7 @@
     a << a
     assert_raise(ArgumentError){a.join}
 
-    def (a = Object.new).to_a
+    def (a = Object.new).to_ary
       [self]
     end
     assert_raise(ArgumentError, '[ruby-core:24150]'){[a].join}
Index: mvm/test/ruby/test_file_exhaustive.rb
===================================================================
--- mvm/test/ruby/test_file_exhaustive.rb	(revision 26939)
+++ mvm/test/ruby/test_file_exhaustive.rb	(revision 26940)
@@ -423,6 +423,8 @@
     end
 
     assert_incompatible_encoding {|d| File.basename(d)}
+    assert_incompatible_encoding {|d| File.basename(d, ".*")}
+    assert_raise(Encoding::CompatibilityError) {File.basename("foo.ext", ".*".encode("utf-16le"))}
   end
 
   def test_dirname
Index: mvm/test/ruby/enc/test_emoji.rb
===================================================================
--- mvm/test/ruby/enc/test_emoji.rb	(revision 26939)
+++ mvm/test/ruby/enc/test_emoji.rb	(revision 26940)
@@ -1,430 +1,442 @@
 require 'test/unit'
 
-class TestRenameSJIS < Test::Unit::TestCase
-  def test_shift_jis
-    assert_raise(ArgumentError) { "".force_encoding("Shift_JIS-DoCoMo") }
-    assert_raise(ArgumentError) { "".force_encoding("Shift_JIS-KDDI") }
-    assert_raise(ArgumentError) { "".force_encoding("Shift_JIS-SoftBank") }
-  end
-end
+module Emoji
 
-class TestUTF8_BLACK_SUN_WITH_RAYS < Test::Unit::TestCase
-  def setup
-    @codes = {
-      "UTF8-DoCoMo"     => utf8_docomo("\u{E63E}"),
-      "UTF8-KDDI"       => utf8_kddi("\u{E488}"),
-      "UTF8-SoftBank"   => utf8_softbank("\u{E04A}"),
-      "UTF-8"           => "\u{2600}",
-    }
+  class TestRenameSJIS < Test::Unit::TestCase
+    def test_shift_jis
+      assert_raise(ArgumentError) { "".force_encoding("Shift_JIS-DoCoMo") }
+      assert_raise(ArgumentError) { "".force_encoding("Shift_JIS-KDDI") }
+      assert_raise(ArgumentError) { "".force_encoding("Shift_JIS-SoftBank") }
+    end
   end
 
-  def test_convert
-    @codes.each do |from_enc, from_str|
-      @codes.each do |to_enc, to_str|
-        next if from_enc == to_enc
-        assert_equal to_str, from_str.encode(to_enc), "convert from #{from_enc} to #{to_enc}"
+  class TestUTF8_BLACK_SUN_WITH_RAYS < Test::Unit::TestCase
+    include Emoji
+
+    def setup
+      @codes = {
+        "UTF8-DoCoMo"     => utf8_docomo("\u{E63E}"),
+        "UTF8-KDDI"       => utf8_kddi("\u{E488}"),
+        "UTF8-SoftBank"   => utf8_softbank("\u{E04A}"),
+        "UTF-8"           => "\u{2600}",
+      }
+    end
+
+    def test_convert
+      @codes.each do |from_enc, from_str|
+        @codes.each do |to_enc, to_str|
+          next if from_enc == to_enc
+          assert_equal to_str, from_str.encode(to_enc), "convert from #{from_enc} to #{to_enc}"
+        end
       end
     end
   end
-end
 
-class TestDoCoMo < Test::Unit::TestCase
-  def setup
-    setup_instance_variable(self)
-  end
+  class TestDoCoMo < Test::Unit::TestCase
+    include Emoji
 
-  def test_encoding_name
-    %w(UTF8-DoCoMo
-       SJIS-DoCoMo).each do |n|
-      assert Encoding.name_list.include?(n), "encoding not found: #{n}"
+    def setup
+      setup_instance_variable(self)
     end
-  end
 
-  def test_comparison
-    assert_not_equal Encoding::UTF_8, Encoding::UTF8_DoCoMo
-    assert_not_equal Encoding::Windows_31J, Encoding::SJIS_DoCoMo
-  end
+    def test_encoding_name
+      %w(UTF8-DoCoMo
+         SJIS-DoCoMo).each do |n|
+        assert Encoding.name_list.include?(n), "encoding not found: #{n}"
+      end
+    end
 
-  def test_from_utf8
-    assert_nothing_raised { assert_equal utf8_docomo(@aiueo_utf8), to_utf8_docomo(@aiueo_utf8) }
-    assert_nothing_raised { assert_equal sjis_docomo(@aiueo_sjis), to_sjis_docomo(@aiueo_utf8) }
-  end
+    def test_comparison
+      assert_not_equal Encoding::UTF_8, Encoding::UTF8_DoCoMo
+      assert_not_equal Encoding::Windows_31J, Encoding::SJIS_DoCoMo
+    end
 
-  def test_from_sjis
-    assert_nothing_raised { assert_equal utf8_docomo(@aiueo_utf8), to_utf8_docomo(@aiueo_sjis) }
-    assert_nothing_raised { assert_equal sjis_docomo(@aiueo_sjis), to_sjis_docomo(@aiueo_sjis) }
-  end
+    def test_from_utf8
+      assert_nothing_raised { assert_equal utf8_docomo(@aiueo_utf8), to_utf8_docomo(@aiueo_utf8) }
+      assert_nothing_raised { assert_equal sjis_docomo(@aiueo_sjis), to_sjis_docomo(@aiueo_utf8) }
+    end
 
-  def test_to_utf8
-    assert_nothing_raised { assert_equal @utf8, to_utf8(@utf8_docomo) }
-    assert_nothing_raised { assert_equal @utf8, to_utf8(@sjis_docomo) }
-  end
+    def test_from_sjis
+      assert_nothing_raised { assert_equal utf8_docomo(@aiueo_utf8), to_utf8_docomo(@aiueo_sjis) }
+      assert_nothing_raised { assert_equal sjis_docomo(@aiueo_sjis), to_sjis_docomo(@aiueo_sjis) }
+    end
 
-  def test_to_sjis
-    assert_raise(Encoding::UndefinedConversionError) { to_sjis(@utf8_docomo) }
-    assert_raise(Encoding::UndefinedConversionError) { to_sjis(@sjis_docomo) }
-  end
+    def test_to_utf8
+      assert_nothing_raised { assert_equal @utf8, to_utf8(@utf8_docomo) }
+      assert_nothing_raised { assert_equal @utf8, to_utf8(@sjis_docomo) }
+    end
 
-  def test_to_eucjp
-    assert_raise(Encoding::UndefinedConversionError) { to_eucjp(@utf8_docomo) }
-    assert_raise(Encoding::UndefinedConversionError) { to_eucjp(@sjis_docomo) }
-  end
+    def test_to_sjis
+      assert_raise(Encoding::UndefinedConversionError) { to_sjis(@utf8_docomo) }
+      assert_raise(Encoding::UndefinedConversionError) { to_sjis(@sjis_docomo) }
+    end
 
-  def test_docomo
-    assert_nothing_raised { assert_equal @utf8_docomo, to_utf8_docomo(@sjis_docomo) }
-    assert_nothing_raised { assert_equal @sjis_docomo, to_sjis_docomo(@utf8_docomo) }
-  end
+    def test_to_eucjp
+      assert_raise(Encoding::UndefinedConversionError) { to_eucjp(@utf8_docomo) }
+      assert_raise(Encoding::UndefinedConversionError) { to_eucjp(@sjis_docomo) }
+    end
 
-  def test_to_kddi
-    assert_nothing_raised { assert_equal @utf8_kddi, to_utf8_kddi(@utf8_docomo) }
-    assert_nothing_raised { assert_equal @sjis_kddi, to_sjis_kddi(@utf8_docomo) }
-    assert_nothing_raised { assert_equal @iso2022jp_kddi, to_iso2022jp_kddi(@utf8_docomo) }
+    def test_docomo
+      assert_nothing_raised { assert_equal @utf8_docomo, to_utf8_docomo(@sjis_docomo) }
+      assert_nothing_raised { assert_equal @sjis_docomo, to_sjis_docomo(@utf8_docomo) }
+    end
 
-    assert_nothing_raised { assert_equal @utf8_kddi, to_utf8_kddi(@sjis_docomo) }
-    assert_nothing_raised { assert_equal @sjis_kddi, to_sjis_kddi(@sjis_docomo) }
-    assert_nothing_raised { assert_equal @iso2022jp_kddi, to_iso2022jp_kddi(@sjis_docomo) }
+    def test_to_kddi
+      assert_nothing_raised { assert_equal @utf8_kddi, to_utf8_kddi(@utf8_docomo) }
+      assert_nothing_raised { assert_equal @sjis_kddi, to_sjis_kddi(@utf8_docomo) }
+      assert_nothing_raised { assert_equal @iso2022jp_kddi, to_iso2022jp_kddi(@utf8_docomo) }
 
-    assert_raise(Encoding::UndefinedConversionError) { to_utf8_kddi(@utf8_docomo_only) }
-    assert_raise(Encoding::UndefinedConversionError) { to_sjis_kddi(@utf8_docomo_only) }
-    assert_raise(Encoding::UndefinedConversionError) { to_iso2022jp_kddi(@utf8_docomo_only) }
+      assert_nothing_raised { assert_equal @utf8_kddi, to_utf8_kddi(@sjis_docomo) }
+      assert_nothing_raised { assert_equal @sjis_kddi, to_sjis_kddi(@sjis_docomo) }
+      assert_nothing_raised { assert_equal @iso2022jp_kddi, to_iso2022jp_kddi(@sjis_docomo) }
 
-    assert_raise(Encoding::UndefinedConversionError) { to_utf8_kddi(@sjis_docomo_only) }
-    assert_raise(Encoding::UndefinedConversionError) { to_sjis_kddi(@sjis_docomo_only) }
-    assert_raise(Encoding::UndefinedConversionError) { to_iso2022jp_kddi(@sjis_docomo_only) }
-  end
+      assert_raise(Encoding::UndefinedConversionError) { to_utf8_kddi(@utf8_docomo_only) }
+      assert_raise(Encoding::UndefinedConversionError) { to_sjis_kddi(@utf8_docomo_only) }
+      assert_raise(Encoding::UndefinedConversionError) { to_iso2022jp_kddi(@utf8_docomo_only) }
 
-  def test_to_softbank
-    assert_nothing_raised { assert_equal @utf8_softbank, to_utf8_softbank(@utf8_docomo) }
-    assert_nothing_raised { assert_equal @sjis_softbank, to_sjis_softbank(@utf8_docomo) }
+      assert_raise(Encoding::UndefinedConversionError) { to_utf8_kddi(@sjis_docomo_only) }
+      assert_raise(Encoding::UndefinedConversionError) { to_sjis_kddi(@sjis_docomo_only) }
+      assert_raise(Encoding::UndefinedConversionError) { to_iso2022jp_kddi(@sjis_docomo_only) }
+    end
 
-    assert_nothing_raised { assert_equal @utf8_softbank, to_utf8_softbank(@sjis_docomo) }
-    assert_nothing_raised { assert_equal @sjis_softbank, to_sjis_softbank(@sjis_docomo) }
+    def test_to_softbank
+      assert_nothing_raised { assert_equal @utf8_softbank, to_utf8_softbank(@utf8_docomo) }
+      assert_nothing_raised { assert_equal @sjis_softbank, to_sjis_softbank(@utf8_docomo) }
 
-    assert_raise(Encoding::UndefinedConversionError) { to_utf8_softbank(@utf8_docomo_only) }
-    assert_raise(Encoding::UndefinedConversionError) { to_sjis_softbank(@utf8_docomo_only) }
+      assert_nothing_raised { assert_equal @utf8_softbank, to_utf8_softbank(@sjis_docomo) }
+      assert_nothing_raised { assert_equal @sjis_softbank, to_sjis_softbank(@sjis_docomo) }
 
-    assert_raise(Encoding::UndefinedConversionError) { to_utf8_softbank(@sjis_docomo_only) }
-    assert_raise(Encoding::UndefinedConversionError) { to_sjis_softbank(@sjis_docomo_only) }
-  end
-end
+      assert_raise(Encoding::UndefinedConversionError) { to_utf8_softbank(@utf8_docomo_only) }
+      assert_raise(Encoding::UndefinedConversionError) { to_sjis_softbank(@utf8_docomo_only) }
 
-class TestKDDI < Test::Unit::TestCase
-  def setup
-    setup_instance_variable(self)
+      assert_raise(Encoding::UndefinedConversionError) { to_utf8_softbank(@sjis_docomo_only) }
+      assert_raise(Encoding::UndefinedConversionError) { to_sjis_softbank(@sjis_docomo_only) }
+    end
   end
 
-  def test_encoding_name
-    %w(UTF8-KDDI
-       SJIS-KDDI
-       ISO-2022-JP-KDDI
-       stateless-ISO-2022-JP-KDDI).each do |n|
-      assert Encoding.name_list.include?(n), "encoding not found: #{n}"
+  class TestKDDI < Test::Unit::TestCase
+    include Emoji
+
+    def setup
+      setup_instance_variable(self)
     end
-  end
 
-  def test_comparison
-    assert_not_equal Encoding::UTF_8, Encoding::UTF8_KDDI
-    assert_not_equal Encoding::Windows_31J, Encoding::SJIS_KDDI
-    assert_not_equal Encoding::ISO_2022_JP, Encoding::ISO_2022_JP_KDDI
-    assert_not_equal Encoding::Stateless_ISO_2022_JP, Encoding::Stateless_ISO_2022_JP_KDDI
-  end
+    def test_encoding_name
+      %w(UTF8-KDDI
+         SJIS-KDDI
+         ISO-2022-JP-KDDI
+         stateless-ISO-2022-JP-KDDI).each do |n|
+        assert Encoding.name_list.include?(n), "encoding not found: #{n}"
+      end
+    end
 
-  def test_from_utf8
-    assert_nothing_raised { assert_equal utf8_kddi(@aiueo_utf8), to_utf8_kddi(@aiueo_utf8) }
-    assert_nothing_raised { assert_equal sjis_kddi(@aiueo_sjis), to_sjis_kddi(@aiueo_utf8) }
-    assert_nothing_raised { assert_equal iso2022jp_kddi(@aiueo_iso2022jp), to_iso2022jp_kddi(@aiueo_utf8) }
-  end
+    def test_comparison
+      assert_not_equal Encoding::UTF_8, Encoding::UTF8_KDDI
+      assert_not_equal Encoding::Windows_31J, Encoding::SJIS_KDDI
+      assert_not_equal Encoding::ISO_2022_JP, Encoding::ISO_2022_JP_KDDI
+      assert_not_equal Encoding::Stateless_ISO_2022_JP, Encoding::Stateless_ISO_2022_JP_KDDI
+    end
 
-  def test_from_sjis
-    assert_nothing_raised { assert_equal utf8_kddi(@aiueo_utf8), to_utf8_kddi(@aiueo_sjis) }
-    assert_nothing_raised { assert_equal sjis_kddi(@aiueo_sjis), to_sjis_kddi(@aiueo_sjis) }
-    assert_nothing_raised { assert_equal iso2022jp_kddi(@aiueo_iso2022jp), to_iso2022jp_kddi(@aiueo_sjis) }
-  end
+    def test_from_utf8
+      assert_nothing_raised { assert_equal utf8_kddi(@aiueo_utf8), to_utf8_kddi(@aiueo_utf8) }
+      assert_nothing_raised { assert_equal sjis_kddi(@aiueo_sjis), to_sjis_kddi(@aiueo_utf8) }
+      assert_nothing_raised { assert_equal iso2022jp_kddi(@aiueo_iso2022jp), to_iso2022jp_kddi(@aiueo_utf8) }
+    end
 
-  def test_from_iso2022jp
-    assert_nothing_raised { assert_equal utf8_kddi(@aiueo_utf8), to_utf8_kddi(@aiueo_iso2022jp) }
-    assert_nothing_raised { assert_equal sjis_kddi(@aiueo_sjis), to_sjis_kddi(@aiueo_iso2022jp) }
-    assert_nothing_raised { assert_equal iso2022jp_kddi(@aiueo_iso2022jp), to_iso2022jp_kddi(@aiueo_iso2022jp) }
-  end
+    def test_from_sjis
+      assert_nothing_raised { assert_equal utf8_kddi(@aiueo_utf8), to_utf8_kddi(@aiueo_sjis) }
+      assert_nothing_raised { assert_equal sjis_kddi(@aiueo_sjis), to_sjis_kddi(@aiueo_sjis) }
+      assert_nothing_raised { assert_equal iso2022jp_kddi(@aiueo_iso2022jp), to_iso2022jp_kddi(@aiueo_sjis) }
+    end
 
-  def test_to_utf8
-    assert_nothing_raised { assert_equal @utf8, to_utf8(@utf8_kddi) }
-    assert_nothing_raised { assert_equal @utf8, to_utf8(@utf8_undoc_kddi) }
-    assert_nothing_raised { assert_equal @utf8, to_utf8(@sjis_kddi) }
-    assert_nothing_raised { assert_equal @utf8, to_utf8(@iso2022jp_kddi) }
-  end
+    def test_from_iso2022jp
+      assert_nothing_raised { assert_equal utf8_kddi(@aiueo_utf8), to_utf8_kddi(@aiueo_iso2022jp) }
+      assert_nothing_raised { assert_equal sjis_kddi(@aiueo_sjis), to_sjis_kddi(@aiueo_iso2022jp) }
+      assert_nothing_raised { assert_equal iso2022jp_kddi(@aiueo_iso2022jp), to_iso2022jp_kddi(@aiueo_iso2022jp) }
+    end
 
-  def test_to_sjis
-    assert_raise(Encoding::UndefinedConversionError) { to_sjis(@utf8_kddi) }
-    assert_raise(Encoding::UndefinedConversionError) { to_sjis(@utf8_undoc_kddi) }
-    assert_raise(Encoding::UndefinedConversionError) { to_sjis(@sjis_kddi) }
-    assert_raise(Encoding::UndefinedConversionError) { to_sjis(@iso2022jp_kddi) }
-  end
+    def test_to_utf8
+      assert_nothing_raised { assert_equal @utf8, to_utf8(@utf8_kddi) }
+      assert_nothing_raised { assert_equal @utf8, to_utf8(@utf8_undoc_kddi) }
+      assert_nothing_raised { assert_equal @utf8, to_utf8(@sjis_kddi) }
+      assert_nothing_raised { assert_equal @utf8, to_utf8(@iso2022jp_kddi) }
+    end
 
-  def test_to_eucjp
-    assert_raise(Encoding::UndefinedConversionError) { to_eucjp(@utf8_kddi) }
-    assert_raise(Encoding::UndefinedConversionError) { to_eucjp(@utf8_undoc_kddi) }
-    assert_raise(Encoding::UndefinedConversionError) { to_eucjp(@sjis_kddi) }
-    assert_raise(Encoding::UndefinedConversionError) { to_eucjp(@iso2022jp_kddi) }
-  end
+    def test_to_sjis
+      assert_raise(Encoding::UndefinedConversionError) { to_sjis(@utf8_kddi) }
+      assert_raise(Encoding::UndefinedConversionError) { to_sjis(@utf8_undoc_kddi) }
+      assert_raise(Encoding::UndefinedConversionError) { to_sjis(@sjis_kddi) }
+      assert_raise(Encoding::UndefinedConversionError) { to_sjis(@iso2022jp_kddi) }
+    end
 
-  def test_kddi
-    assert_nothing_raised { assert_equal @utf8_kddi, to_utf8_kddi(@sjis_kddi) }
-    assert_nothing_raised { assert_equal @utf8_kddi, to_utf8_kddi(@iso2022jp_kddi) }
-    assert_nothing_raised { assert_equal @sjis_kddi, to_sjis_kddi(@sjis_kddi) }
-    assert_nothing_raised { assert_equal @sjis_kddi, to_sjis_kddi(@utf8_undoc_kddi) }
-    assert_nothing_raised { assert_equal @sjis_kddi, to_sjis_kddi(@iso2022jp_kddi) }
-    assert_nothing_raised { assert_equal @iso2022jp_kddi, to_iso2022jp_kddi(@sjis_kddi) }
-    assert_nothing_raised { assert_equal @iso2022jp_kddi, to_iso2022jp_kddi(@utf8_undoc_kddi) }
-    assert_nothing_raised { assert_equal @iso2022jp_kddi, to_iso2022jp_kddi(@iso2022jp_kddi) }
-  end
+    def test_to_eucjp
+      assert_raise(Encoding::UndefinedConversionError) { to_eucjp(@utf8_kddi) }
+      assert_raise(Encoding::UndefinedConversionError) { to_eucjp(@utf8_undoc_kddi) }
+      assert_raise(Encoding::UndefinedConversionError) { to_eucjp(@sjis_kddi) }
+      assert_raise(Encoding::UndefinedConversionError) { to_eucjp(@iso2022jp_kddi) }
+    end
 
-  def test_to_docomo
-    assert_nothing_raised { assert_equal @utf8_docomo, to_utf8_docomo(@utf8_kddi) }
-    assert_nothing_raised { assert_equal @sjis_docomo, to_sjis_docomo(@utf8_kddi) }
+    def test_kddi
+      assert_nothing_raised { assert_equal @utf8_kddi, to_utf8_kddi(@sjis_kddi) }
+      assert_nothing_raised { assert_equal @utf8_kddi, to_utf8_kddi(@iso2022jp_kddi) }
+      assert_nothing_raised { assert_equal @sjis_kddi, to_sjis_kddi(@sjis_kddi) }
+      assert_nothing_raised { assert_equal @sjis_kddi, to_sjis_kddi(@utf8_undoc_kddi) }
+      assert_nothing_raised { assert_equal @sjis_kddi, to_sjis_kddi(@iso2022jp_kddi) }
+      assert_nothing_raised { assert_equal @iso2022jp_kddi, to_iso2022jp_kddi(@sjis_kddi) }
+      assert_nothing_raised { assert_equal @iso2022jp_kddi, to_iso2022jp_kddi(@utf8_undoc_kddi) }
+      assert_nothing_raised { assert_equal @iso2022jp_kddi, to_iso2022jp_kddi(@iso2022jp_kddi) }
+    end
 
-    assert_nothing_raised { assert_equal @utf8_docomo, to_utf8_docomo(@utf8_undoc_kddi) }
-    assert_nothing_raised { assert_equal @sjis_docomo, to_sjis_docomo(@utf8_undoc_kddi) }
+    def test_to_docomo
+      assert_nothing_raised { assert_equal @utf8_docomo, to_utf8_docomo(@utf8_kddi) }
+      assert_nothing_raised { assert_equal @sjis_docomo, to_sjis_docomo(@utf8_kddi) }
 
-    assert_nothing_raised { assert_equal @utf8_docomo, to_utf8_docomo(@sjis_kddi) }
-    assert_nothing_raised { assert_equal @sjis_docomo, to_sjis_docomo(@sjis_kddi) }
+      assert_nothing_raised { assert_equal @utf8_docomo, to_utf8_docomo(@utf8_undoc_kddi) }
+      assert_nothing_raised { assert_equal @sjis_docomo, to_sjis_docomo(@utf8_undoc_kddi) }
 
-    assert_nothing_raised { assert_equal @utf8_docomo, to_utf8_docomo(@iso2022jp_kddi) }
-    assert_nothing_raised { assert_equal @sjis_docomo, to_sjis_docomo(@iso2022jp_kddi) }
+      assert_nothing_raised { assert_equal @utf8_docomo, to_utf8_docomo(@sjis_kddi) }
+      assert_nothing_raised { assert_equal @sjis_docomo, to_sjis_docomo(@sjis_kddi) }
 
-    assert_raise(Encoding::UndefinedConversionError) { assert_equal @utf8_docomo, to_utf8_docomo(@utf8_kddi_only) }
-    assert_raise(Encoding::UndefinedConversionError) { assert_equal @sjis_docomo, to_sjis_docomo(@utf8_kddi_only) }
+      assert_nothing_raised { assert_equal @utf8_docomo, to_utf8_docomo(@iso2022jp_kddi) }
+      assert_nothing_raised { assert_equal @sjis_docomo, to_sjis_docomo(@iso2022jp_kddi) }
 
-    assert_raise(Encoding::UndefinedConversionError) { assert_equal @utf8_docomo, to_utf8_docomo(@utf8_undoc_kddi_only) }
-    assert_raise(Encoding::UndefinedConversionError) { assert_equal @sjis_docomo, to_sjis_docomo(@utf8_undoc_kddi_only) }
+      assert_raise(Encoding::UndefinedConversionError) { assert_equal @utf8_docomo, to_utf8_docomo(@utf8_kddi_only) }
+      assert_raise(Encoding::UndefinedConversionError) { assert_equal @sjis_docomo, to_sjis_docomo(@utf8_kddi_only) }
 
-    assert_raise(Encoding::UndefinedConversionError) { assert_equal @utf8_docomo, to_utf8_docomo(@sjis_kddi_only) }
-    assert_raise(Encoding::UndefinedConversionError) { assert_equal @sjis_docomo, to_sjis_docomo(@sjis_kddi_only) }
+      assert_raise(Encoding::UndefinedConversionError) { assert_equal @utf8_docomo, to_utf8_docomo(@utf8_undoc_kddi_only) }
+      assert_raise(Encoding::UndefinedConversionError) { assert_equal @sjis_docomo, to_sjis_docomo(@utf8_undoc_kddi_only) }
 
-    assert_raise(Encoding::UndefinedConversionError) { assert_equal @utf8_docomo, to_utf8_docomo(@iso2022jp_kddi_only) }
-    assert_raise(Encoding::UndefinedConversionError) { assert_equal @sjis_docomo, to_sjis_docomo(@iso2022jp_kddi_only) }
-  end
+      assert_raise(Encoding::UndefinedConversionError) { assert_equal @utf8_docomo, to_utf8_docomo(@sjis_kddi_only) }
+      assert_raise(Encoding::UndefinedConversionError) { assert_equal @sjis_docomo, to_sjis_docomo(@sjis_kddi_only) }
 
-  def test_to_softbank
-    assert_nothing_raised { assert_equal @utf8_softbank, to_utf8_softbank(@utf8_kddi) }
-    assert_nothing_raised { assert_equal @sjis_softbank, to_sjis_softbank(@utf8_kddi) }
+      assert_raise(Encoding::UndefinedConversionError) { assert_equal @utf8_docomo, to_utf8_docomo(@iso2022jp_kddi_only) }
+      assert_raise(Encoding::UndefinedConversionError) { assert_equal @sjis_docomo, to_sjis_docomo(@iso2022jp_kddi_only) }
+    end
 
-    assert_nothing_raised { assert_equal @utf8_softbank, to_utf8_softbank(@utf8_undoc_kddi) }
-    assert_nothing_raised { assert_equal @sjis_softbank, to_sjis_softbank(@utf8_undoc_kddi) }
+    def test_to_softbank
+      assert_nothing_raised { assert_equal @utf8_softbank, to_utf8_softbank(@utf8_kddi) }
+      assert_nothing_raised { assert_equal @sjis_softbank, to_sjis_softbank(@utf8_kddi) }
 
-    assert_nothing_raised { assert_equal @utf8_softbank, to_utf8_softbank(@sjis_kddi) }
-    assert_nothing_raised { assert_equal @sjis_softbank, to_sjis_softbank(@sjis_kddi) }
+      assert_nothing_raised { assert_equal @utf8_softbank, to_utf8_softbank(@utf8_undoc_kddi) }
+      assert_nothing_raised { assert_equal @sjis_softbank, to_sjis_softbank(@utf8_undoc_kddi) }
 
-    assert_nothing_raised { assert_equal @utf8_softbank, to_utf8_softbank(@iso2022jp_kddi) }
-    assert_nothing_raised { assert_equal @sjis_softbank, to_sjis_softbank(@iso2022jp_kddi) }
+      assert_nothing_raised { assert_equal @utf8_softbank, to_utf8_softbank(@sjis_kddi) }
+      assert_nothing_raised { assert_equal @sjis_softbank, to_sjis_softbank(@sjis_kddi) }
 
-    assert_raise(Encoding::UndefinedConversionError) { assert_equal @utf8_softbank, to_utf8_softbank(@utf8_kddi_only) }
-    assert_raise(Encoding::UndefinedConversionError) { assert_equal @sjis_softbank, to_sjis_softbank(@utf8_kddi_only) }
+      assert_nothing_raised { assert_equal @utf8_softbank, to_utf8_softbank(@iso2022jp_kddi) }
+      assert_nothing_raised { assert_equal @sjis_softbank, to_sjis_softbank(@iso2022jp_kddi) }
 
-    assert_raise(Encoding::UndefinedConversionError) { assert_equal @utf8_softbank, to_utf8_softbank(@utf8_undoc_kddi_only) }
-    assert_raise(Encoding::UndefinedConversionError) { assert_equal @sjis_softbank, to_sjis_softbank(@utf8_undoc_kddi_only) }
+      assert_raise(Encoding::UndefinedConversionError) { assert_equal @utf8_softbank, to_utf8_softbank(@utf8_kddi_only) }
+      assert_raise(Encoding::UndefinedConversionError) { assert_equal @sjis_softbank, to_sjis_softbank(@utf8_kddi_only) }
 
-    assert_raise(Encoding::UndefinedConversionError) { assert_equal @utf8_softbank, to_utf8_softbank(@sjis_kddi_only) }
-    assert_raise(Encoding::UndefinedConversionError) { assert_equal @sjis_softbank, to_sjis_softbank(@sjis_kddi_only) }
+      assert_raise(Encoding::UndefinedConversionError) { assert_equal @utf8_softbank, to_utf8_softbank(@utf8_undoc_kddi_only) }
+      assert_raise(Encoding::UndefinedConversionError) { assert_equal @sjis_softbank, to_sjis_softbank(@utf8_undoc_kddi_only) }
 
-    assert_raise(Encoding::UndefinedConversionError) { assert_equal @utf8_softbank, to_utf8_softbank(@iso2022jp_kddi_only) }
-    assert_raise(Encoding::UndefinedConversionError) { assert_equal @sjis_softbank, to_sjis_softbank(@iso2022jp_kddi_only) }
-  end
-end
+      assert_raise(Encoding::UndefinedConversionError) { assert_equal @utf8_softbank, to_utf8_softbank(@sjis_kddi_only) }
+      assert_raise(Encoding::UndefinedConversionError) { assert_equal @sjis_softbank, to_sjis_softbank(@sjis_kddi_only) }
 
-class TestSoftBank < Test::Unit::TestCase
-  def setup
-    setup_instance_variable(self)
+      assert_raise(Encoding::UndefinedConversionError) { assert_equal @utf8_softbank, to_utf8_softbank(@iso2022jp_kddi_only) }
+      assert_raise(Encoding::UndefinedConversionError) { assert_equal @sjis_softbank, to_sjis_softbank(@iso2022jp_kddi_only) }
+    end
   end
 
-  def test_encoding_name
-    %w(UTF8-SoftBank
-       SJIS-SoftBank).each do |n|
-      assert Encoding.name_list.include?(n), "encoding not found: #{n}"
+  class TestSoftBank < Test::Unit::TestCase
+    include Emoji
+
+    def setup
+      setup_instance_variable(self)
     end
-  end
 
-  def test_comparison
-    assert_not_equal Encoding::UTF_8, Encoding::UTF8_SoftBank
-    assert_not_equal Encoding::Windows_31J, Encoding::SJIS_SoftBank
-  end
+    def test_encoding_name
+      %w(UTF8-SoftBank
+         SJIS-SoftBank).each do |n|
+        assert Encoding.name_list.include?(n), "encoding not found: #{n}"
+      end
+    end
 
-  def test_from_utf8
-    assert_nothing_raised { assert_equal utf8_softbank(@aiueo_utf8), to_utf8_softbank(@aiueo_utf8) }
-    assert_nothing_raised { assert_equal sjis_softbank(@aiueo_sjis), to_sjis_softbank(@aiueo_utf8) }
-  end
+    def test_comparison
+      assert_not_equal Encoding::UTF_8, Encoding::UTF8_SoftBank
+      assert_not_equal Encoding::Windows_31J, Encoding::SJIS_SoftBank
+    end
 
-  def test_from_sjis
-    assert_nothing_raised { assert_equal utf8_softbank(@aiueo_utf8), to_utf8_softbank(@aiueo_sjis) }
-    assert_nothing_raised { assert_equal sjis_softbank(@aiueo_sjis), to_sjis_softbank(@aiueo_sjis) }
-  end
+    def test_from_utf8
+      assert_nothing_raised { assert_equal utf8_softbank(@aiueo_utf8), to_utf8_softbank(@aiueo_utf8) }
+      assert_nothing_raised { assert_equal sjis_softbank(@aiueo_sjis), to_sjis_softbank(@aiueo_utf8) }
+    end
 
-  def test_to_utf8
-    assert_nothing_raised { assert_equal @utf8, to_utf8(@utf8_softbank) }
-    assert_nothing_raised { assert_equal @utf8, to_utf8(@sjis_softbank) }
-  end
+    def test_from_sjis
+      assert_nothing_raised { assert_equal utf8_softbank(@aiueo_utf8), to_utf8_softbank(@aiueo_sjis) }
+      assert_nothing_raised { assert_equal sjis_softbank(@aiueo_sjis), to_sjis_softbank(@aiueo_sjis) }
+    end
 
-  def test_to_sjis
-    assert_raise(Encoding::UndefinedConversionError) { to_sjis(@utf8_softbank) }
-    assert_raise(Encoding::UndefinedConversionError) { to_sjis(@sjis_softbank) }
-  end
+    def test_to_utf8
+      assert_nothing_raised { assert_equal @utf8, to_utf8(@utf8_softbank) }
+      assert_nothing_raised { assert_equal @utf8, to_utf8(@sjis_softbank) }
+    end
 
-  def test_to_eucjp
-    assert_raise(Encoding::UndefinedConversionError) { to_eucjp(@utf8_softbank) }
-    assert_raise(Encoding::UndefinedConversionError) { to_eucjp(@sjis_softbank) }
-  end
+    def test_to_sjis
+      assert_raise(Encoding::UndefinedConversionError) { to_sjis(@utf8_softbank) }
+      assert_raise(Encoding::UndefinedConversionError) { to_sjis(@sjis_softbank) }
+    end
 
-  def test_softbank
-    assert_nothing_raised { assert_equal @utf8_softbank, to_utf8_softbank(@sjis_softbank) }
-    assert_nothing_raised { assert_equal @sjis_softbank, to_sjis_softbank(@utf8_softbank) }
-  end
+    def test_to_eucjp
+      assert_raise(Encoding::UndefinedConversionError) { to_eucjp(@utf8_softbank) }
+      assert_raise(Encoding::UndefinedConversionError) { to_eucjp(@sjis_softbank) }
+    end
 
-  def test_to_docomo
-    assert_nothing_raised { assert_equal @utf8_docomo, to_utf8_docomo(@utf8_softbank) }
-    assert_nothing_raised { assert_equal @sjis_docomo, to_sjis_docomo(@utf8_softbank) }
+    def test_softbank
+      assert_nothing_raised { assert_equal @utf8_softbank, to_utf8_softbank(@sjis_softbank) }
+      assert_nothing_raised { assert_equal @sjis_softbank, to_sjis_softbank(@utf8_softbank) }
+    end
 
-    assert_nothing_raised { assert_equal @utf8_docomo, to_utf8_docomo(@sjis_softbank) }
-    assert_nothing_raised { assert_equal @sjis_docomo, to_sjis_docomo(@sjis_softbank) }
+    def test_to_docomo
+      assert_nothing_raised { assert_equal @utf8_docomo, to_utf8_docomo(@utf8_softbank) }
+      assert_nothing_raised { assert_equal @sjis_docomo, to_sjis_docomo(@utf8_softbank) }
 
-    assert_raise(Encoding::UndefinedConversionError) { to_utf8_docomo(@utf8_softbank_only) }
-    assert_raise(Encoding::UndefinedConversionError) { to_sjis_docomo(@utf8_softbank_only) }
+      assert_nothing_raised { assert_equal @utf8_docomo, to_utf8_docomo(@sjis_softbank) }
+      assert_nothing_raised { assert_equal @sjis_docomo, to_sjis_docomo(@sjis_softbank) }
 
-    assert_raise(Encoding::UndefinedConversionError) { to_utf8_docomo(@sjis_softbank_only) }
-    assert_raise(Encoding::UndefinedConversionError) { to_sjis_docomo(@sjis_softbank_only) }
-  end
+      assert_raise(Encoding::UndefinedConversionError) { to_utf8_docomo(@utf8_softbank_only) }
+      assert_raise(Encoding::UndefinedConversionError) { to_sjis_docomo(@utf8_softbank_only) }
 
-  def test_to_kddi
-    assert_nothing_raised { assert_equal @utf8_kddi, to_utf8_kddi(@utf8_softbank) }
-    assert_nothing_raised { assert_equal @sjis_kddi, to_sjis_kddi(@utf8_softbank) }
-    assert_nothing_raised { assert_equal @iso2022jp_kddi, to_iso2022jp_kddi(@utf8_softbank) }
+      assert_raise(Encoding::UndefinedConversionError) { to_utf8_docomo(@sjis_softbank_only) }
+      assert_raise(Encoding::UndefinedConversionError) { to_sjis_docomo(@sjis_softbank_only) }
+    end
 
-    assert_nothing_raised { assert_equal @utf8_kddi, to_utf8_kddi(@sjis_softbank) }
-    assert_nothing_raised { assert_equal @sjis_kddi, to_sjis_kddi(@sjis_softbank) }
-    assert_nothing_raised { assert_equal @iso2022jp_kddi, to_iso2022jp_kddi(@sjis_softbank) }
+    def test_to_kddi
+      assert_nothing_raised { assert_equal @utf8_kddi, to_utf8_kddi(@utf8_softbank) }
+      assert_nothing_raised { assert_equal @sjis_kddi, to_sjis_kddi(@utf8_softbank) }
+      assert_nothing_raised { assert_equal @iso2022jp_kddi, to_iso2022jp_kddi(@utf8_softbank) }
 
-    assert_raise(Encoding::UndefinedConversionError) { to_utf8_kddi(@utf8_softbank_only) }
-    assert_raise(Encoding::UndefinedConversionError) { to_sjis_kddi(@utf8_softbank_only) }
-    assert_raise(Encoding::UndefinedConversionError) { to_iso2022jp_kddi(@utf8_softbank_only) }
+      assert_nothing_raised { assert_equal @utf8_kddi, to_utf8_kddi(@sjis_softbank) }
+      assert_nothing_raised { assert_equal @sjis_kddi, to_sjis_kddi(@sjis_softbank) }
+      assert_nothing_raised { assert_equal @iso2022jp_kddi, to_iso2022jp_kddi(@sjis_softbank) }
 
-    assert_raise(Encoding::UndefinedConversionError) { to_utf8_kddi(@sjis_softbank_only) }
-    assert_raise(Encoding::UndefinedConversionError) { to_sjis_kddi(@sjis_softbank_only) }
-    assert_raise(Encoding::UndefinedConversionError) { to_iso2022jp_kddi(@sjis_softbank_only) }
+      assert_raise(Encoding::UndefinedConversionError) { to_utf8_kddi(@utf8_softbank_only) }
+      assert_raise(Encoding::UndefinedConversionError) { to_sjis_kddi(@utf8_softbank_only) }
+      assert_raise(Encoding::UndefinedConversionError) { to_iso2022jp_kddi(@utf8_softbank_only) }
+
+      assert_raise(Encoding::UndefinedConversionError) { to_utf8_kddi(@sjis_softbank_only) }
+      assert_raise(Encoding::UndefinedConversionError) { to_sjis_kddi(@sjis_softbank_only) }
+      assert_raise(Encoding::UndefinedConversionError) { to_iso2022jp_kddi(@sjis_softbank_only) }
+    end
   end
-end
 
-private
+  private
 
-def setup_instance_variable(obj)
-  obj.instance_eval do
-    @aiueo_utf8 = "\u{3042}\u{3044}\u{3046}\u{3048}\u{304A}"
-    @aiueo_sjis = to_sjis(@aiueo_utf8)
-    @aiueo_iso2022jp = to_iso2022jp(@aiueo_utf8)
+  def setup_instance_variable(obj)
+    obj.instance_eval do
+      @aiueo_utf8 = "\u{3042}\u{3044}\u{3046}\u{3048}\u{304A}"
+      @aiueo_sjis = to_sjis(@aiueo_utf8)
+      @aiueo_iso2022jp = to_iso2022jp(@aiueo_utf8)
 
-    @utf8 = "\u{2600}"
+      @utf8 = "\u{2600}"
 
-    @utf8_docomo = utf8_docomo("\u{E63E}")
-    @sjis_docomo = sjis_docomo("\xF8\x9F")
-    @utf8_docomo_only = utf8_docomo("\u{E6B1}")
-    @sjis_docomo_only = sjis_docomo("\xF9\x55")
+      @utf8_docomo = utf8_docomo("\u{E63E}")
+      @sjis_docomo = sjis_docomo("\xF8\x9F")
+      @utf8_docomo_only = utf8_docomo("\u{E6B1}")
+      @sjis_docomo_only = sjis_docomo("\xF9\x55")
 
-    @utf8_kddi = utf8_kddi("\u{E488}")
-    @utf8_undoc_kddi = utf8_kddi("\u{EF60}")
-    @sjis_kddi = sjis_kddi("\xF6\x60")
-    @iso2022jp_kddi = iso2022jp_kddi("\x1B$B\x75\x41\x1B(B")
-    @stateless_iso2022jp_kddi = stateless_iso2022jp_kddi("\x92\xF5\xC1")
-    @utf8_kddi_only = utf8_kddi("\u{E5B3}")
-    @utf8_undoc_kddi_only = utf8_kddi("\u{F0D0}")
-    @sjis_kddi_only = sjis_kddi("\xF7\xD0")
-    @iso2022jp_kddi_only = iso2022jp_kddi("\x1B$B\x78\x52\x1B(B")
-    @stateless_iso2022jp_kddi_only = stateless_iso2022jp_kddi("\x92\xF8\xD2")
+      @utf8_kddi = utf8_kddi("\u{E488}")
+      @utf8_undoc_kddi = utf8_kddi("\u{EF60}")
+      @sjis_kddi = sjis_kddi("\xF6\x60")
+      @iso2022jp_kddi = iso2022jp_kddi("\x1B$B\x75\x41\x1B(B")
+      @stateless_iso2022jp_kddi = stateless_iso2022jp_kddi("\x92\xF5\xC1")
+      @utf8_kddi_only = utf8_kddi("\u{E5B3}")
+      @utf8_undoc_kddi_only = utf8_kddi("\u{F0D0}")
+      @sjis_kddi_only = sjis_kddi("\xF7\xD0")
+      @iso2022jp_kddi_only = iso2022jp_kddi("\x1B$B\x78\x52\x1B(B")
+      @stateless_iso2022jp_kddi_only = stateless_iso2022jp_kddi("\x92\xF8\xD2")
 
-    @utf8_softbank = utf8_softbank("\u{E04A}")
-    @sjis_softbank = sjis_softbank("\xF9\x8B")
-    @utf8_softbank_only = utf8_softbank("\u{E524}")
-    @sjis_softbank_only = sjis_softbank("\xFB\xC4")
+      @utf8_softbank = utf8_softbank("\u{E04A}")
+      @sjis_softbank = sjis_softbank("\xF9\x8B")
+      @utf8_softbank_only = utf8_softbank("\u{E524}")
+      @sjis_softbank_only = sjis_softbank("\xFB\xC4")
+    end
   end
-end
 
-def utf8(str)
-  str.force_encoding("UTF-8")
-end
+  def utf8(str)
+    str.force_encoding("UTF-8")
+  end
 
-def to_utf8(str)
-  str.encode("UTF-8")
-end
+  def to_utf8(str)
+    str.encode("UTF-8")
+  end
 
-def to_sjis(str)
-  str.encode("Windows-31J")
-end
+  def to_sjis(str)
+    str.encode("Windows-31J")
+  end
 
-def to_eucjp(str)
-  str.encode("eucJP-ms")
-end
+  def to_eucjp(str)
+    str.encode("eucJP-ms")
+  end
 
-def to_iso2022jp(str)
-  str.encode("ISO-2022-JP")
-end
+  def to_iso2022jp(str)
+    str.encode("ISO-2022-JP")
+  end
 
-def utf8_docomo(str)
-  str.force_encoding("UTF8-DoCoMo")
-end
+  def utf8_docomo(str)
+    str.force_encoding("UTF8-DoCoMo")
+  end
 
-def to_utf8_docomo(str)
-  str.encode("UTF8-DoCoMo")
-end
+  def to_utf8_docomo(str)
+    str.encode("UTF8-DoCoMo")
+  end
 
-def utf8_kddi(str)
-  str.force_encoding("UTF8-KDDI")
-end
+  def utf8_kddi(str)
+    str.force_encoding("UTF8-KDDI")
+  end
 
-def to_utf8_kddi(str)
-  str.encode("UTF8-KDDI")
-end
+  def to_utf8_kddi(str)
+    str.encode("UTF8-KDDI")
+  end
 
-def utf8_softbank(str)
-  str.force_encoding("UTF8-SoftBank")
-end
+  def utf8_softbank(str)
+    str.force_encoding("UTF8-SoftBank")
+  end
 
-def to_utf8_softbank(str)
-  str.encode("UTF8-SoftBank")
-end
+  def to_utf8_softbank(str)
+    str.encode("UTF8-SoftBank")
+  end
 
-def sjis_docomo(str)
-  str.force_encoding("SJIS-DoCoMo")
-end
+  def sjis_docomo(str)
+    str.force_encoding("SJIS-DoCoMo")
+  end
 
-def to_sjis_docomo(str)
-  str.encode("SJIS-DoCoMo")
-end
+  def to_sjis_docomo(str)
+    str.encode("SJIS-DoCoMo")
+  end
 
-def sjis_kddi(str)
-  str.force_encoding("SJIS-KDDI")
-end
+  def sjis_kddi(str)
+    str.force_encoding("SJIS-KDDI")
+  end
 
-def to_sjis_kddi(str)
-  str.encode("SJIS-KDDI")
-end
+  def to_sjis_kddi(str)
+    str.encode("SJIS-KDDI")
+  end
 
-def sjis_softbank(str)
-  str.force_encoding("SJIS-SoftBank")
-end
+  def sjis_softbank(str)
+    str.force_encoding("SJIS-SoftBank")
+  end
 
-def to_sjis_softbank(str)
-  str.encode("SJIS-SoftBank")
-end
+  def to_sjis_softbank(str)
+    str.encode("SJIS-SoftBank")
+  end
 
-def iso2022jp_kddi(str)
-  str.force_encoding("ISO-2022-JP-KDDI")
-end
+  def iso2022jp_kddi(str)
+    str.force_encoding("ISO-2022-JP-KDDI")
+  end
 
-def to_iso2022jp_kddi(str)
-  str.encode("ISO-2022-JP-KDDI")
-end
+  def to_iso2022jp_kddi(str)
+    str.encode("ISO-2022-JP-KDDI")
+  end
 
-def stateless_iso2022jp_kddi(str)
-  str.force_encoding("stateless-ISO-2022-JP-KDDI")
-end
+  def stateless_iso2022jp_kddi(str)
+    str.force_encoding("stateless-ISO-2022-JP-KDDI")
+  end
 
-def to_stateless_iso2022jp_kddi(str)
-  str.encode("stateless-ISO-2022-JP-KDDI")
+  def to_stateless_iso2022jp_kddi(str)
+    str.encode("stateless-ISO-2022-JP-KDDI")
+  end
+
 end
Index: mvm/test/ruby/test_enum.rb
===================================================================
--- mvm/test/ruby/test_enum.rb	(revision 26939)
+++ mvm/test/ruby/test_enum.rb	(revision 26940)
@@ -311,38 +311,6 @@
     assert_equal([2,1,3,2,1], @obj.reverse_each.to_a)
   end
 
-  def test_join
-    ofs = $,
-    assert_equal("abc", ("a".."c").join(""))
-    assert_equal("a-b-c", ("a".."c").join("-"))
-    $, = "-"
-    assert_equal("a-b-c", ("a".."c").join())
-    $, = nil
-    assert_equal("abc", ("a".."c").join())
-    assert_equal("123", (1..3).join())
-    assert_raise(TypeError, '[ruby-core:24172]') {("a".."c").join(1)}
-    class << (e = Object.new.extend(Enumerable))
-      def each
-        yield self
-      end
-    end
-    assert_raise(ArgumentError){e.join("")}
-    assert_raise(ArgumentError){[e].join("")}
-    e = Class.new {
-      include Enumerable
-      def initialize(*args)
-        @e = args
-      end
-      def each
-        @e.each {|e| yield e}
-      end
-    }
-    e = e.new(1, e.new(2, e.new(3, e.new(4, 5))))
-    assert_equal("1:2:3:4:5", e.join(':'), '[ruby-core:24196]')
-  ensure
-    $, = ofs
-  end
-
   def test_chunk
     e = [].chunk {|elt| true }
     assert_equal([], e.to_a)
Index: mvm/test/ruby/test_file.rb
===================================================================
--- mvm/test/ruby/test_file.rb	(revision 26939)
+++ mvm/test/ruby/test_file.rb	(revision 26940)
@@ -164,6 +164,10 @@
       tst = realdir.sub(/#{Regexp.escape(File::SEPARATOR)}/, '\0\0\0')
       assert_equal(realdir, File.realpath(tst))
       assert_equal(realdir, File.realpath(".", tst))
+      if File::ALT_SEPARATOR
+        bug2961 = '[ruby-core:28653]'
+        assert_equal(realdir, File.realpath(realdir.tr(File::SEPARATOR, File::ALT_SEPARATOR)), bug2961)
+      end
     }
   end
 
Index: mvm/test/ruby/test_io.rb
===================================================================
--- mvm/test/ruby/test_io.rb	(revision 26939)
+++ mvm/test/ruby/test_io.rb	(revision 26940)
@@ -150,6 +150,16 @@
     r.close
   end
 
+  def test_each_codepoint
+    t = make_tempfile
+    bug2959 = '[ruby-core:28650]'
+    a = ""
+    File.open(t, 'rt') {|f|
+      f.each_codepoint {|c| a << c}
+    }
+    assert_equal("foo\nbar\nbaz\n", a, bug2959)
+  end
+
   def test_rubydev33072
     assert_raise(Errno::ENOENT, "[ruby-dev:33072]") do
       File.read("empty", nil, nil, {})
@@ -1386,6 +1396,23 @@
     assert_in_out_err(["-", t.path], "print while $<.gets", %w(foo bar baz), [])
   end
 
+  def test_print_separators
+    $, = ':'
+    $\ = "\n"
+    r, w = IO.pipe
+    w.print('a')
+    w.print('a','b','c')
+    w.close
+    assert_equal("a\n", r.gets)
+    assert_equal("a:b:c\n", r.gets)
+    assert_nil r.gets
+    r.close
+    
+  ensure
+    $, = nil
+    $\ = nil
+  end
+
   def test_putc
     pipe(proc do |w|
       w.putc "A"
Index: mvm/test/ruby/test_rand.rb
===================================================================
--- mvm/test/ruby/test_rand.rb	(revision 26939)
+++ mvm/test/ruby/test_rand.rb	(revision 26940)
@@ -387,4 +387,14 @@
     r2.rand(0x100)
     assert(r1 == r2)
   end
+
+  def test_fork_shuffle
+    pid = fork do
+        (1..10).to_a.shuffle
+        raise 'default seed is not set' if srand == 0
+    end
+    p2, st = Process.waitpid2(pid)
+    assert(st.success?)
+  rescue NotImplementedError, ArgumentError
+  end
 end
Index: mvm/test/uri/test_common.rb
===================================================================
--- mvm/test/uri/test_common.rb	(revision 26939)
+++ mvm/test/uri/test_common.rb	(revision 26940)
@@ -49,6 +49,31 @@
     assert_equal(expected, Kernel::URI("http://www.ruby-lang.org/"))
     assert_raise(NoMethodError) { Object.new.URI("http://www.ruby-lang.org/") }
   end
+
+  def test_encode_www_component
+    assert_equal("+%21%22%23%24%25%26%27%28%29*%2B%2C-.%2F09%3A%3B%3C%3D%3E%3F%40" \
+                 "AZ%5B%5C%5D%5E_%60az%7B%7C%7D%7E",
+                 URI.encode_www_component(" !\"\#$%&'()*+,-./09:;<=>?@AZ[\\]^_`az{|}~"))
+  end
+
+  def test_decode_www_component
+    assert_equal(" !\"\#$%&'()*+,-./09:;<=>?@AZ[\\]^_`az{|}~",
+                 URI.decode_www_component(
+                   "+%21%22%23%24%25%26%27%28%29*%2B%2C-.%2F09%3A%3B%3C%3D%3E%3F%40" \
+                   "AZ%5B%5C%5D%5E_%60az%7B%7C%7D%7E"))
+  end
+
+  def test_encode_www_form
+    assert_equal("a=1", URI.encode_www_form("a" => "1"))
+    assert_equal("a=1", URI.encode_www_form(a: 1))
+    assert_equal("a=1", URI.encode_www_form([["a", "1"]]))
+    assert_equal("a=1", URI.encode_www_form([[:a, 1]]))
+    expected = "a=1&%E3%81%82=%E6%BC%A2"
+    assert_equal(expected, URI.encode_www_form("a" => "1", "\u3042" => "\u6F22"))
+    assert_equal(expected, URI.encode_www_form(a: 1, :"\u3042" => "\u6F22"))
+    assert_equal(expected, URI.encode_www_form([["a", "1"], ["\u3042", "\u6F22"]]))
+    assert_equal(expected, URI.encode_www_form([[:a, 1], [:"\u3042", "\u6F22"]]))
+  end
 end
 
 
Index: mvm/file.c
===================================================================
--- mvm/file.c	(revision 26939)
+++ mvm/file.c	(revision 26940)
@@ -2539,7 +2539,11 @@
 #if defined __CYGWIN__ || defined DOSISH
 #define DOSISH_UNC
 #define DOSISH_DRIVE_LETTER
-#define isdirsep(x) ((x) == '/' || (x) == '\\')
+#define FILE_ALT_SEPARATOR '\\'
+#endif
+#ifdef FILE_ALT_SEPARATOR
+#define isdirsep(x) ((x) == '/' || (x) == FILE_ALT_SEPARATOR)
+static const char file_alt_separator[] = {FILE_ALT_SEPARATOR, '\0'};
 #else
 #define isdirsep(x) ((x) == '/')
 #endif
@@ -2735,8 +2739,6 @@
     (void)(extenc || (extenc = rb_default_external_encoding())),\
     rb_enc_associate(result, extenc))
 
-#define is_absolute_path(path) ruby_absolute_path_p(path)
-
 VALUE
 rb_home_dir(const char *user, VALUE result)
 {
@@ -2850,7 +2852,7 @@
 	}
     }
 #endif
-    else if (!is_absolute_path(s)) {
+    else if (!rb_is_absolute_path(s)) {
 	if (!NIL_P(dname)) {
 	    file_expand_path(dname, Qnil, abs_mode, result);
 	    BUFINIT();
@@ -2881,7 +2883,7 @@
 	p = buf + (s - b);
 	BUFCHECK(bdiff >= buflen);
 	memset(buf, '/', p - buf);
-	rb_enc_copy(result, fname);
+	rb_enc_associate(result, rb_enc_check(result, fname));
     }
     if (p > buf && p[-1] == '/')
 	--p;
@@ -3133,6 +3135,8 @@
 static void
 realpath_rec(long *prefixlenp, VALUE *resolvedp, char *unresolved, VALUE loopcheck, int strict, int last)
 {
+    ID resolving;
+    CONST_ID(resolving, "resolving");
     while (*unresolved) {
         char *testname = unresolved;
         char *unresolved_firstsep = rb_path_next(unresolved);
@@ -3158,7 +3162,7 @@
             rb_str_cat(testpath, testname, testnamelen);
             checkval = rb_hash_aref(loopcheck, testpath);
             if (!NIL_P(checkval)) {
-                if (checkval == ID2SYM(rb_intern("resolving"))) {
+                if (checkval == ID2SYM(resolving)) {
                     errno = ELOOP;
                     rb_sys_fail(RSTRING_PTR(testpath));
                 }
@@ -3186,7 +3190,7 @@
                     volatile VALUE link;
                     char *link_prefix, *link_names;
                     long link_prefixlen;
-                    rb_hash_aset(loopcheck, testpath, ID2SYM(rb_intern("resolving")));
+                    rb_hash_aset(loopcheck, testpath, ID2SYM(resolving));
                     link = rb_file_s_readlink(rb_cFile, testpath);
                     link_prefix = RSTRING_PTR(link);
                     link_names = skiproot(link_prefix);
@@ -3221,9 +3225,9 @@
     volatile VALUE unresolved_path;
     VALUE loopcheck;
     volatile VALUE curdir = Qnil;
-    
+
     char *path_names = NULL, *basedir_names = NULL, *curdir_names = NULL;
-    char *ptr;
+    char *ptr, *prefixptr = NULL;
 
     rb_secure(2);
 
@@ -3257,11 +3261,21 @@
     resolved = rb_str_new(ptr, curdir_names - ptr);
 
   root_found:
-    ptr = chompdirsep(RSTRING_PTR(resolved));
+    prefixptr = RSTRING_PTR(resolved);
+    prefixlen = RSTRING_LEN(resolved);
+    ptr = chompdirsep(prefixptr);
     if (*ptr) {
-        rb_str_set_len(resolved, ptr - RSTRING_PTR(resolved) + 1);
+        prefixlen = ++ptr - prefixptr;
+        rb_str_set_len(resolved, prefixlen);
     }
-    prefixlen = RSTRING_LEN(resolved);
+#ifdef FILE_ALT_SEPARATOR
+    while (prefixptr < ptr) {
+	if (*prefixptr == FILE_ALT_SEPARATOR) {
+	    *prefixptr = '/';
+	}
+	prefixptr = CharNext(prefixptr);
+    }
+#endif
 
     loopcheck = rb_hash_new();
     if (curdir_names)
@@ -3372,9 +3386,15 @@
     long f, n;
 
     if (rb_scan_args(argc, argv, "11", &fname, &fext) == 2) {
+	rb_encoding *enc;
 	StringValue(fext);
+	if (!rb_enc_asciicompat(enc = rb_enc_get(fext))) {
+	    rb_raise(rb_eEncCompatError, "ascii incompatible character encodings: %s",
+		     rb_enc_name(enc));
+	}
     }
     FilePathStringValue(fname);
+    if (!NIL_P(fext)) rb_enc_check(fname, fext);
     if (RSTRING_LEN(fname) == 0 || !*(name = RSTRING_PTR(fname)))
 	return rb_str_new_shared(fname);
     name = skipprefix(name);
@@ -4745,7 +4765,7 @@
 }
 
 int
-ruby_absolute_path_p(const char *path)
+rb_is_absolute_path(const char *path)
 {
 #ifdef DOSISH_DRIVE_LETTER
     if (has_drive_letter(path) && isdirsep(path[2])) return 1;
@@ -4775,7 +4795,7 @@
     const char *p0 = StringValueCStr(path);
     char *p = 0, *s;
 
-    if (!is_absolute_path(p0)) {
+    if (!rb_is_absolute_path(p0)) {
 	char *buf = my_getcwd();
 	VALUE newpath;
 
@@ -4912,7 +4932,7 @@
 	expanded = 1;
     }
 
-    if (expanded || is_absolute_path(f) || is_explicit_relative(f)) {
+    if (expanded || rb_is_absolute_path(f) || is_explicit_relative(f)) {
 	if (safe_level >= 1 && !fpath_check(fname)) {
 	    rb_raise(rb_eSecurityError, "loading from unsafe path %s", f);
 	}
@@ -4983,7 +5003,7 @@
 	expanded = 1;
     }
 
-    if (expanded || is_absolute_path(f) || is_explicit_relative(f)) {
+    if (expanded || rb_is_absolute_path(f) || is_explicit_relative(f)) {
 	if (safe_level >= 1 && !fpath_check(path)) {
 	    rb_raise(rb_eSecurityError, "loading from unsafe path %s", f);
 	}
@@ -5150,7 +5170,7 @@
     rb_define_singleton_method(rb_cFile, "join",   rb_file_s_join, -2);
 
 #ifdef DOSISH
-    rb_define_const(rb_cFile, "ALT_SEPARATOR", rb_obj_freeze(rb_usascii_str_new2("\\")));
+    rb_define_const(rb_cFile, "ALT_SEPARATOR", rb_obj_freeze(rb_usascii_str_new2(file_alt_separator)));
 #else
     rb_define_const(rb_cFile, "ALT_SEPARATOR", Qnil);
 #endif
Index: mvm/random.c
===================================================================
--- mvm/random.c	(revision 26939)
+++ mvm/random.c	(revision 26940)
@@ -137,10 +137,6 @@
     unsigned int *p = mt->state;
     int j;
 
-    /* if init_genrand() has not been called, */
-    /* a default initial seed is used         */
-    if (!genrand_initialized(mt)) init_genrand(mt, 5489U);
-
     mt->left = N;
     mt->next = mt->state;
 
@@ -157,6 +153,7 @@
 static unsigned int
 genrand_int32(struct MT *mt)
 {
+    /* mt must be initialized */
     unsigned int y;
 
     if (--mt->left <= 0) next_state(mt);
@@ -175,6 +172,7 @@
 static double
 genrand_real(struct MT *mt)
 {
+    /* mt must be initialized */
     unsigned int a = genrand_int32(mt)>>5, b = genrand_int32(mt)>>6;
     return(a*67108864.0+b)*(1.0/9007199254740992.0);
 }
@@ -184,6 +182,7 @@
 static double
 genrand_real2(struct MT *mt)
 {
+    /* mt must be initialized */
     unsigned int a = genrand_int32(mt), b = genrand_int32(mt);
     return int_pair_to_real_inclusive(a, b);
 }
@@ -217,23 +216,34 @@
 
 #define DEFAULT_SEED_CNT 4
 
-struct Random {
-    rb_random_t rnd;
-    unsigned int initial[DEFAULT_SEED_CNT];
-};
-
 #define default_rand (*(rb_random_t *)DATA_PTR(*rb_vm_specific_ptr(rb_vmkey_default_rand)))
 
+static VALUE rand_init(struct MT *mt, VALUE vseed);
+static VALUE random_seed(void);
+
+static struct MT *
+default_mt(void)
+{
+    rb_random_t *r = &default_rand;
+    struct MT *mt = &r->mt;
+    if (!genrand_initialized(mt)) {
+	r->seed = rand_init(mt, random_seed());
+    }
+    return mt;
+}
+
 unsigned int
 rb_genrand_int32(void)
 {
-    return genrand_int32(&default_rand.mt);
+    struct MT *mt = default_mt();
+    return genrand_int32(mt);
 }
 
 double
 rb_genrand_real(void)
 {
-    return genrand_real(&default_rand.mt);
+    struct MT *mt = default_mt();
+    return genrand_real(mt);
 }
 
 #define BDIGITS(x) (RBIGNUM_DIGITS(x))
@@ -304,8 +314,6 @@
 #define id_minus '-'
 #define id_plus  '+'
 
-static VALUE random_seed(void);
-
 /* :nodoc: */
 static void
 random_mark(void *ptr)
@@ -759,6 +767,7 @@
 static unsigned long
 limited_rand(struct MT *mt, unsigned long limit)
 {
+    /* mt must be initialized */
     int i;
     unsigned long val, mask;
 
@@ -780,6 +789,7 @@
 static VALUE
 limited_big_rand(struct MT *mt, struct RBignum *limit)
 {
+    /* mt must be initialized */
     unsigned long mask, lim, rnd;
     struct RBignum *val;
     long i, len;
@@ -830,10 +840,7 @@
 unsigned long
 rb_rand_internal(unsigned long i)
 {
-    struct MT *mt = &default_rand.mt;
-    if (!genrand_initialized(mt)) {
-	rand_init(mt, random_seed());
-    }
+    struct MT *mt = default_mt();
     return limited_rand(mt, i);
 }
 
@@ -904,6 +911,7 @@
 static VALUE
 rand_int(struct MT *mt, VALUE vmax, int restrictive)
 {
+    /* mt must be initialized */
     long max;
     unsigned long r;
 
@@ -1109,11 +1117,8 @@
 rb_f_rand(int argc, VALUE *argv, VALUE obj)
 {
     VALUE vmax, r;
-    struct MT *mt = &default_rand.mt;
+    struct MT *mt = default_mt();
 
-    if (!genrand_initialized(mt)) {
-	rand_init(mt, random_seed());
-    }
     if (argc == 0) goto zero_arg;
     rb_scan_args(argc, argv, "01", &vmax);
     if (NIL_P(vmax)) goto zero_arg;
@@ -1126,20 +1131,26 @@
 }
 
 static st_index_t hashseed;
-static struct Random initial_rand;
 
-static struct Random *
-init_randomseed(struct Random *r)
+static VALUE
+init_randomseed(struct MT *mt, unsigned int initial[DEFAULT_SEED_CNT])
 {
-    fill_random_seed(r->initial);
-    init_by_array(&r->rnd.mt, r->initial, DEFAULT_SEED_CNT);
-    return r;
+    VALUE seed;
+    fill_random_seed(initial);
+    init_by_array(mt, initial, DEFAULT_SEED_CNT);
+    seed = make_seed_value(initial);
+    memset(initial, 0, DEFAULT_SEED_LEN);
+    return seed;
 }
 
 void
 Init_RandomSeed(void)
 {
-    struct MT *mt = &init_randomseed(&initial_rand)->rnd.mt;
+    VALUE rv = *rb_vm_specific_ptr(rb_vmkey_default_rand) = random_alloc(0);
+    rb_random_t *r = DATA_PTR(rv);
+    unsigned int initial[DEFAULT_SEED_CNT];
+    struct MT *mt = &r->mt;
+    VALUE seed = init_randomseed(mt, initial);
 
     hashseed = genrand_int32(mt);
 #if SIZEOF_ST_INDEX_T*CHAR_BIT > 4*8
@@ -1154,11 +1165,23 @@
     hashseed <<= 32;
     hashseed |= genrand_int32(mt);
 #endif
+
+    r->seed = seed;
 }
 
 void
 InitVM_RandomSeed(void)
 {
+    VALUE *rp = rb_vm_specific_ptr(rb_vmkey_default_rand), rv = *rp;
+    unsigned int initial[DEFAULT_SEED_CNT];
+    rb_random_t *r;
+
+    if (rv) return;		/* main VM */
+    *rp = rv = random_alloc(0);
+    r = DATA_PTR(rv);
+    init_randomseed(&r->mt, initial);
+    r->seed = make_seed_value(initial);
+    memset(initial, 0, DEFAULT_SEED_LEN);
 }
 
 st_index_t
@@ -1168,24 +1191,13 @@
 }
 
 static void
-InitVM_RandomSeed2(void)
+Init_RandomSeed2(void)
 {
-    unsigned int *ini, initial[DEFAULT_SEED_CNT];
-    VALUE rv = random_alloc(0);
-    rb_random_t *r = DATA_PTR(rv);
+    VALUE seed = default_rand.seed;
 
-    *rb_vm_specific_ptr(rb_vmkey_default_rand) = rv;
-    if (initial_rand.rnd.seed) {
-	fill_random_seed(initial);
-	init_by_array(&r->mt, initial, DEFAULT_SEED_CNT);
-	ini = initial;
+    if (RB_TYPE_P(seed, T_BIGNUM)) {
+	RBASIC(seed)->klass = rb_cBignum;
     }
-    else {
-	*r = initial_rand.rnd;
-	initial_rand.rnd.seed = Qtrue;
-	ini = initial_rand.initial;
-    }
-    r->seed = make_seed_value(ini);
 }
 
 void
@@ -1204,7 +1216,7 @@
 void
 InitVM_Random(void)
 {
-    InitVM_RandomSeed2();
+    Init_RandomSeed2();
     rb_define_global_function("srand", rb_f_srand, -1);
     rb_define_global_function("rand", rb_f_rand, -1);
 

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]