[macruby-changes] [249] MacRuby/branches/testing

source_changes at macosforge.org source_changes at macosforge.org
Thu Jun 5 01:33:06 PDT 2008


Revision: 249
          http://trac.macosforge.org/projects/ruby/changeset/249
Author:   lsansonetti at apple.com
Date:     2008-06-05 01:33:02 -0700 (Thu, 05 Jun 2008)

Log Message:
-----------
merge with trunk

Modified Paths:
--------------
    MacRuby/branches/testing/ChangeLog
    MacRuby/branches/testing/Makefile.in
    MacRuby/branches/testing/README
    MacRuby/branches/testing/README.ja
    MacRuby/branches/testing/array.c
    MacRuby/branches/testing/benchmark/bmx_temp.rb
    MacRuby/branches/testing/bin/gem
    MacRuby/branches/testing/blockinlining.c
    MacRuby/branches/testing/bootstraptest/test_eval.rb
    MacRuby/branches/testing/bootstraptest/test_jump.rb
    MacRuby/branches/testing/bootstraptest/test_knownbug.rb
    MacRuby/branches/testing/bootstraptest/test_literal.rb
    MacRuby/branches/testing/bootstraptest/test_syntax.rb
    MacRuby/branches/testing/bootstraptest/test_thread.rb
    MacRuby/branches/testing/bs.c
    MacRuby/branches/testing/bs.h
    MacRuby/branches/testing/class.c
    MacRuby/branches/testing/common.mk
    MacRuby/branches/testing/compile.c
    MacRuby/branches/testing/configure.in
    MacRuby/branches/testing/cont.c
    MacRuby/branches/testing/dir.c
    MacRuby/branches/testing/doc/NEWS
    MacRuby/branches/testing/encoding.c
    MacRuby/branches/testing/enum.c
    MacRuby/branches/testing/enumerator.c
    MacRuby/branches/testing/error.c
    MacRuby/branches/testing/eval.c
    MacRuby/branches/testing/eval_error.c
    MacRuby/branches/testing/eval_intern.h
    MacRuby/branches/testing/eval_jump.c
    MacRuby/branches/testing/ext/nkf/nkf-utf8/nkf.c
    MacRuby/branches/testing/ext/nkf/nkf.c
    MacRuby/branches/testing/ext/openssl/ossl_bn.c
    MacRuby/branches/testing/ext/openssl/ossl_pkcs5.c
    MacRuby/branches/testing/ext/openssl/ossl_pkey_dh.c
    MacRuby/branches/testing/ext/openssl/ossl_pkey_dsa.c
    MacRuby/branches/testing/ext/openssl/ossl_rand.c
    MacRuby/branches/testing/ext/openssl/ossl_x509store.c
    MacRuby/branches/testing/ext/purelib.rb
    MacRuby/branches/testing/ext/stringio/stringio.c
    MacRuby/branches/testing/ext/strscan/strscan.c
    MacRuby/branches/testing/ext/zlib/extconf.rb
    MacRuby/branches/testing/file.c
    MacRuby/branches/testing/gc.c
    MacRuby/branches/testing/hash.c
    MacRuby/branches/testing/id.c
    MacRuby/branches/testing/id.h
    MacRuby/branches/testing/include/ruby/defines.h
    MacRuby/branches/testing/include/ruby/encoding.h
    MacRuby/branches/testing/include/ruby/intern.h
    MacRuby/branches/testing/include/ruby/node.h
    MacRuby/branches/testing/include/ruby/ruby.h
    MacRuby/branches/testing/include/ruby/win32.h
    MacRuby/branches/testing/include/ruby.h
    MacRuby/branches/testing/insns.def
    MacRuby/branches/testing/instruby.rb
    MacRuby/branches/testing/io.c
    MacRuby/branches/testing/iseq.c
    MacRuby/branches/testing/keywords
    MacRuby/branches/testing/lex.c.blt
    MacRuby/branches/testing/lex.c.src
    MacRuby/branches/testing/lib/delegate.rb
    MacRuby/branches/testing/lib/erb.rb
    MacRuby/branches/testing/lib/net/imap.rb
    MacRuby/branches/testing/lib/rake.rb
    MacRuby/branches/testing/lib/singleton.rb
    MacRuby/branches/testing/lib/un.rb
    MacRuby/branches/testing/lib/webrick/httpservlet/abstract.rb
    MacRuby/branches/testing/lib/webrick/httpservlet/cgi_runner.rb
    MacRuby/branches/testing/lib/webrick/httpservlet/cgihandler.rb
    MacRuby/branches/testing/lib/webrick/httpservlet/filehandler.rb
    MacRuby/branches/testing/load.c
    MacRuby/branches/testing/main.c
    MacRuby/branches/testing/marshal.c
    MacRuby/branches/testing/math.c
    MacRuby/branches/testing/misc/ruby-mode.el
    MacRuby/branches/testing/missing/crypt.c
    MacRuby/branches/testing/missing/vsnprintf.c
    MacRuby/branches/testing/mkconfig.rb
    MacRuby/branches/testing/numeric.c
    MacRuby/branches/testing/objc.m
    MacRuby/branches/testing/object.c
    MacRuby/branches/testing/pack.c
    MacRuby/branches/testing/parse.y
    MacRuby/branches/testing/proc.c
    MacRuby/branches/testing/process.c
    MacRuby/branches/testing/rational.c
    MacRuby/branches/testing/re.c
    MacRuby/branches/testing/regenc.h
    MacRuby/branches/testing/regerror.c
    MacRuby/branches/testing/regexec.c
    MacRuby/branches/testing/ruby.c
    MacRuby/branches/testing/sample-macruby/CircleView/CircleView.rb
    MacRuby/branches/testing/sample-macruby/CircleView/main.m
    MacRuby/branches/testing/sample-macruby/Scripts/hello_world.rb
    MacRuby/branches/testing/signal.c
    MacRuby/branches/testing/sprintf.c
    MacRuby/branches/testing/string.c
    MacRuby/branches/testing/struct.c
    MacRuby/branches/testing/template/insns.inc.tmpl
    MacRuby/branches/testing/test/erb/test_erb.rb
    MacRuby/branches/testing/test/net/imap/test_imap.rb
    MacRuby/branches/testing/test/ruby/envutil.rb
    MacRuby/branches/testing/test/ruby/test_array.rb
    MacRuby/branches/testing/test/ruby/test_class.rb
    MacRuby/branches/testing/test/ruby/test_continuation.rb
    MacRuby/branches/testing/test/ruby/test_enum.rb
    MacRuby/branches/testing/test/ruby/test_eval.rb
    MacRuby/branches/testing/test/ruby/test_file.rb
    MacRuby/branches/testing/test/ruby/test_file_exhaustive.rb
    MacRuby/branches/testing/test/ruby/test_io.rb
    MacRuby/branches/testing/test/ruby/test_m17n.rb
    MacRuby/branches/testing/test/ruby/test_method.rb
    MacRuby/branches/testing/test/ruby/test_module.rb
    MacRuby/branches/testing/test/ruby/test_numeric.rb
    MacRuby/branches/testing/test/ruby/test_objc.rb
    MacRuby/branches/testing/test/ruby/test_objectspace.rb
    MacRuby/branches/testing/test/ruby/test_pack.rb
    MacRuby/branches/testing/test/ruby/test_proc.rb
    MacRuby/branches/testing/test/ruby/test_process.rb
    MacRuby/branches/testing/test/ruby/test_regexp.rb
    MacRuby/branches/testing/test/ruby/test_rubyoptions.rb
    MacRuby/branches/testing/test/ruby/test_signal.rb
    MacRuby/branches/testing/test/ruby/test_sprintf.rb
    MacRuby/branches/testing/test/ruby/test_string.rb
    MacRuby/branches/testing/test/ruby/test_struct.rb
    MacRuby/branches/testing/test/ruby/test_thread.rb
    MacRuby/branches/testing/test/ruby/test_utf16.rb
    MacRuby/branches/testing/test/ruby/test_utf32.rb
    MacRuby/branches/testing/test/test_delegate.rb
    MacRuby/branches/testing/test/webrick/test_cgi.rb
    MacRuby/branches/testing/test/webrick/test_filehandler.rb
    MacRuby/branches/testing/test/webrick/utils.rb
    MacRuby/branches/testing/thread.c
    MacRuby/branches/testing/thread_pthread.c
    MacRuby/branches/testing/thread_win32.c
    MacRuby/branches/testing/time.c
    MacRuby/branches/testing/tool/instruction.rb
    MacRuby/branches/testing/transcode.c
    MacRuby/branches/testing/util.c
    MacRuby/branches/testing/variable.c
    MacRuby/branches/testing/version.h
    MacRuby/branches/testing/vm.c
    MacRuby/branches/testing/vm.h
    MacRuby/branches/testing/vm_core.h
    MacRuby/branches/testing/vm_dump.c
    MacRuby/branches/testing/vm_evalbody.c
    MacRuby/branches/testing/vm_insnhelper.c
    MacRuby/branches/testing/vm_opts.h

Added Paths:
-----------
    MacRuby/branches/testing/include/ruby/mvm.h
    MacRuby/branches/testing/lib/cmath.rb
    MacRuby/branches/testing/markgc.c
    MacRuby/branches/testing/sample-macruby/Scripts/circle.rb
    MacRuby/branches/testing/test/ruby/test_argf.rb
    MacRuby/branches/testing/test/ruby/test_big5.rb
    MacRuby/branches/testing/test/ruby/test_cp949.rb
    MacRuby/branches/testing/test/ruby/test_euc_jp.rb
    MacRuby/branches/testing/test/ruby/test_euc_kr.rb
    MacRuby/branches/testing/test/ruby/test_euc_tw.rb
    MacRuby/branches/testing/test/ruby/test_gb18030.rb
    MacRuby/branches/testing/test/ruby/test_gbk.rb
    MacRuby/branches/testing/test/ruby/test_iso_8859.rb
    MacRuby/branches/testing/test/ruby/test_koi8.rb
    MacRuby/branches/testing/test/ruby/test_require.rb
    MacRuby/branches/testing/test/ruby/test_shift_jis.rb
    MacRuby/branches/testing/test/ruby/test_windows_1251.rb
    MacRuby/branches/testing/test/webrick/.htaccess
    MacRuby/branches/testing/test/webrick/webrick_long_filename.cgi
    MacRuby/branches/testing/vm_eval.c
    MacRuby/branches/testing/vm_method.c

Removed Paths:
-------------
    MacRuby/branches/testing/bcc32/
    MacRuby/branches/testing/cygwin/
    MacRuby/branches/testing/djgpp/
    MacRuby/branches/testing/eval_method.c
    MacRuby/branches/testing/ext/tk/
    MacRuby/branches/testing/ext/win32ole/
    MacRuby/branches/testing/lib/generator.rb
    MacRuby/branches/testing/lib/require_relative.rb
    MacRuby/branches/testing/lib/rubygems/gem_open_uri.rb
    MacRuby/branches/testing/lib/rubygems/open-uri.rb
    MacRuby/branches/testing/vms/
    MacRuby/branches/testing/win32/
    MacRuby/branches/testing/wince/

Modified: MacRuby/branches/testing/ChangeLog
===================================================================
--- MacRuby/branches/testing/ChangeLog	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/ChangeLog	2008-06-05 08:33:02 UTC (rev 249)
@@ -1,3 +1,897 @@
+Tue Jun  3 01:21:51 2008  Yusuke Endoh  <mame at tsg.ne.jp>
+
+	* test/ruby/test_method.rb: add a test.
+
+Tue Jun  3 00:26:48 2008  Yusuke Endoh  <mame at tsg.ne.jp>
+
+	* marshal.c (w_object): add a check for modification of array during
+	  its dump.
+
+Mon Jun  2 22:27:57 2008  Yusuke Endoh  <mame at tsg.ne.jp>
+
+	* enc/iso_8859_5.c: Large omicron should lowercase to small omicron.
+
+	* test/ruby/test_big5.rb, test/ruby/test_cp949.rb,
+	  test/ruby/test_euc_jp.rb, test/ruby/test_euc_kr.rb,
+	  test/ruby/test_euc_tw.rb, test/ruby/test_gb18030.rb,
+	  test/ruby/test_gbk.rb, test/ruby/test_iso_8859.rb,
+	  test/ruby/test_koi8.rb, test/ruby/test_shift_jis.rb,
+	  test/ruby/test_windows_1251.rb: new tests for encoding.
+
+	* test/ruby/test_utf16.rb, test/ruby/test_utf32.rb,
+	  test/ruby/test_regexp.rb: add tests.
+
+Mon Jun  2 21:56:47 2008  Yusuke Endoh  <mame at tsg.ne.jp>
+
+	* test/ruby/test_file.rb: add tests for uninitialized object.
+
+	* test/ruby/test_class.rb: ditto.
+
+	* test/ruby/test_thread.rb: ditto.
+
+Mon Jun  2 21:44:15 2008  Yusuke Endoh  <mame at tsg.ne.jp>
+
+	* re.c: fix SEGV by Regexp.allocate.names, Match.allocate.names, etc.
+
+	* test/ruby/test_regexp.rb: add tests for above.
+
+	* io.c: fix SEGV by IO.allocate.print, etc.
+
+	* test/ruby/test_io.rb: add tests for above.
+
+Mon Jun  2 19:17:47 2008  Tanaka Akira  <akr at fsij.org>
+
+	* test/ruby/test_argf.rb (teardown): remove renamed temporary files.
+
+Mon Jun  2 18:51:15 2008  Nobuyoshi Nakada  <nobu at ruby-lang.org>
+
+	* lib/un.rb (wait_writable): wait until target files can be
+	  written actually.
+
+	* win32/Makefile.sub (LDSHARED_0, LINK_SO): get rid of failure of
+	  mt.exe.
+
+Mon Jun  2 16:26:17 2008  Akinori MUSHA  <knu at iDaemons.org>
+
+	* lib/delegate.rb (Delegator::MethodDelegation#respond_to):
+	  respond_to? should now take optional second argument; submitted
+	  by Jeremy Kemper <jeremy at bitsweat.net> in [ruby-core:17045].
+
+Mon Jun  2 16:14:18 2008  Akinori MUSHA  <knu at iDaemons.org>
+
+	* lib/erb.rb (ERB::Compiler::TrimScanner#scan_line): Oops.  This
+	  change did not apply to trunk.  Backed out.
+
+Mon Jun  2 16:08:24 2008  Akinori MUSHA  <knu at iDaemons.org>
+
+	* lib/erb.rb (ERB::Compiler::TrimScanner#scan_line): Fix a bug
+	  where tokens are not yilelded one by one.
+
+	* test/erb/test_erb.rb (TestERBCore#_test_01)
+	  (TestERBCore#test_02_safe_04): The expected value should come
+	  first for assert_equal().
+
+Mon Jun  2 13:06:38 2008  NAKAMURA Usaku  <usa at ruby-lang.org>
+
+	* mkconfig.rb: hide build path from rbconfig.rb.
+
+Mon Jun  2 08:46:52 2008  Nobuyoshi Nakada  <nobu at ruby-lang.org>
+
+	* util.c (ruby_strtod, dtoa): initialize more variables for error
+	  handling.
+
+Mon Jun  2 04:55:05 2008  Nobuyoshi Nakada  <nobu at ruby-lang.org>
+
+	* suppress warnings on cygwin, mingw and mswin.
+
+Mon Jun  2 04:35:32 2008  NARUSE, Yui  <naruse at ruby-lang.org>
+
+	* enc/gb18030.c (gb18030_code_to_mbc): add 0x80000000
+	  for 4bytes character.
+
+Mon Jun  2 03:52:04 2008  Nobuyoshi Nakada  <nobu at ruby-lang.org>
+
+	* ruby.c (set_arg0): reverted used variable definition.
+
+Mon Jun  2 03:23:25 2008  NARUSE, Yui  <naruse at ruby-lang.org>
+
+	* enc/gb18030.c (gb18030_mbc_to_code): mask by 0x7FFFFFFF
+	  because OnigCodePoint will be used as 32bit signed int.
+	  Masking by 0x7FFFFFFF is ok on GB18030;
+	  Minumum 4bytes character is 0x81308130.
+
+Sun Jun  1 22:29:35 2008  NARUSE, Yui  <naruse at ruby-lang.org>
+
+	* rational.c (string_to_r_internal): use rb_isdigit.
+
+	* marshal.c (long_toobig): use %zd.
+
+	* ruby.c (set_arg0): move unused variable definition.
+
+Sun Jun  1 12:18:12 2008  NARUSE, Yui  <naruse at ruby-lang.org>
+
+	* insns.def (DEFINE_INSN): subtract of pointers is ptrdiff_t.
+	  this is not int on 64bit system.
+
+	* vm_dump.c (control_frame_dump): ditto.
+
+	* vm_dump.c (stack_dump_each): ditto.
+
+	* vm_dump.c (debug_print_register): ditto.
+
+	* vm_dump.c (debug_print_pre): ditto.
+
+	* transcode.c (str_transcode): ditto.
+
+Sun Jun  1 10:32:18 2008  Tanaka Akira  <akr at fsij.org>
+
+	* test/ruby/envutil.rb (assert_normal_exit): show coredump status.
+
+Sat May 31 23:33:34 2008  Akinori MUSHA  <knu at iDaemons.org>
+
+	* README, README.ja: Add a note about default C flags.
+
+Sat May 31 23:02:00 2008  Tanaka Akira  <akr at fsij.org>
+
+	* gc.c (count_objects): clear given hash.
+
+Sat May 31 20:28:10 2008  Yusuke Endoh  <mame at tsg.ne.jp>
+
+	* test/ruby/test_regexp.rb: add tests.
+
+Sat May 31 19:11:39 2008  NARUSE, Yui  <naruse at ruby-lang.org>
+
+	* enc/utf_16{be,le}.c (utf16{be,le}_code_to_mbc):
+	  fix codepoint to bytes.
+
+Sat May 31 18:28:17 2008  Nobuyoshi Nakada  <nobu at ruby-lang.org>
+
+	* suppress warnings with -Wwrite-string.
+
+Sat May 31 18:26:33 2008  Yukihiro Matsumoto  <matz at ruby-lang.org>
+
+	* array.c (rb_ary_delete_if): should return enumerator if no block
+	  is given.  [ruby-dev:34901]
+
+Sat May 31 15:58:08 2008  Nobuyoshi Nakada  <nobu at ruby-lang.org>
+
+	* Makefile.in, configure.in (warnflags): defaulted to -Wall
+	  -Wno-parentheses with gcc.  [ruby-dev:34810]
+
+Sat May 31 15:17:36 2008  Nobuyoshi Nakada  <nobu at ruby-lang.org>
+
+	* include/ruby/mvm.h: new header file for MVM, and moved rb_vm_t and
+	  rb_thread_t from vm_core.h.
+
+Sat May 31 12:02:23 2008  Tanaka Akira  <akr at fsij.org>
+
+	* test/ruby/envutil.rb (assert_normal_exit): show pid when fail.
+
+Fri May 30 23:55:56 2008  Kazuhiro NISHIYAMA  <zn at mbf.nifty.com>
+
+	* test/ruby/test_rubyoptions.rb: add a test of RUBY_DESCRIPTION.
+
+Fri May 30 22:47:17 2008  Yusuke Endoh  <mame at tsg.ne.jp>
+
+	* test/ruby/test_regexp.rb: add tests.
+
+Fri May 30 22:40:53 2008  Yusuke Endoh  <mame at tsg.ne.jp>
+
+	* test/ruby/test_signal.rb: add tests to achieve over 80% test
+	  coverage of signal.c.
+
+Fri May 30 22:28:03 2008  Yusuke Endoh  <mame at tsg.ne.jp>
+
+	* signal.c (esignal_signo): fix SignalException#signo which returned
+	  nil absolutely.
+
+	* signal.c (esignal_init): always prepend "SIG" to a string that is
+	  returned by SignalException#signm.
+
+Fri May 30 22:17:39 2008  Yusuke Endoh  <mame at tsg.ne.jp>
+
+	* test/ruby/test_argf.rb: rename a conflicting method name.
+
+	* test/ruby/test_string.rb: ditto.
+
+	* test/ruby/test_io.rb: ditto.
+
+Fri May 30 22:14:37 2008  Yusuke Endoh  <mame at tsg.ne.jp>
+
+	* compile.c (defined_expr): fix SEGV by defined?([1]).
+
+Fri May 30 12:18:43 2008  Nobuyoshi Nakada  <nobu at ruby-lang.org>
+
+	* common.mk (prelude.c): simply depends on PREP.  [ruby-dev:34877]
+
+	* enc/make_encdb.rb, enc/trans/make_transdb.rb: ditto.
+
+Fri May 30 10:55:42 2008  Nobuyoshi Nakada  <nobu at ruby-lang.org>
+
+	* vm_core.h (struct rb_unblock_callback), thread.c
+	  (set_unblock_function), thread_{pthread,win32}.c (native_sleep):
+	  extracted from struct rb_thread_struct.
+
+	* thread.c (reset_unblock_function): not check interrupts at leaving
+	  blocking region.  [ruby-dev:34874]
+
+Fri May 30 06:09:31 2008  NARUSE, Yui  <naruse at ruby-lang.org>
+
+	* enc/utf_8.c: add UTF8-MAC (UTF-8-MAC).
+
+Fri May 30 04:17:13 2008  Akinori MUSHA  <knu at iDaemons.org>
+
+	* enum.c (enum_count, count_all_i, Init_Enumerable),
+	  array.c (rb_ary_count): If no argument or block is given, count
+	  the number of all elements.
+
+Fri May 30 03:12:18 2008  Akinori MUSHA  <knu at iDaemons.org>
+
+	* ext/openssl/ossl_bn.c (ossl_bn_s_rand, ossl_bn_s_pseudo_rand):
+	  Int should be enough here.
+
+Fri May 30 02:35:00 2008  Akinori MUSHA  <knu at iDaemons.org>
+
+	* ext/openssl/ossl_bn.c (ossl_bn_s_rand, ossl_bn_s_pseudo_rand),
+	  ext/openssl/ossl_pkey_dh.c (ossl_dh_s_generate)
+	  (ossl_dh_initialize),
+	  ext/openssl/ossl_pkey_dsa.c (ossl_dsa_s_generate),
+	  ext/openssl/ossl_rand.c (ossl_rand_bytes)
+	  (ossl_rand_pseudo_bytes, ossl_rand_egd_bytes),
+	  ext/openssl/ossl_x509store.c (ossl_x509stctx_set_error): Do not
+	  use FIX2INT() without checking the value type.  Use NUM2INT()
+	  instead; found by akr in [ruby-dev:34890].
+
+Fri May 30 02:08:20 2008  Yusuke Endoh  <mame at tsg.ne.jp>
+
+	* signal.c (esignal_init): handle a non-integer argument correctly,
+	  allowing SignalException.new(:INT).
+
+Fri May 30 00:59:47 2008  Yusuke Endoh  <mame at tsg.ne.jp>
+
+	* test/ruby/test_regexp.rb: add tests.
+
+Thu May 29 22:51:05 2008  Yusuke Endoh  <mame at tsg.ne.jp>
+
+	* test/ruby/test_require.rb: add a test for load with wrap flag, to
+	  achieve 100% test coverage of eval_jump.c.
+
+Thu May 29 22:47:53 2008  Yusuke Endoh  <mame at tsg.ne.jp>
+
+	* test/ruby/test_argf.rb: new tests for ARGF, to achieve over 85% test
+	  coverage of file.c.
+
+	* test/ruby/test_io.rb: add tests.
+
+Thu May 29 22:41:48 2008  Yusuke Endoh  <mame at tsg.ne.jp>
+
+	* io.c (argf_readchar): raise EOFError, synchronizing IO#readchar.
+
+Thu May 29 22:29:39 2008  Yusuke Endoh  <mame at tsg.ne.jp>
+
+	* io.c (argf_external_encoding, argf_internal_encoding): fix SEGV by
+	  ARGF.external_encoding.
+
+Thu May 29 17:52:31 2008  Nobuyoshi Nakada  <nobu at ruby-lang.org>
+
+	* ext/zlib/extconf.rb: search zlib1, and regard mswin32 later than VC6
+	  as WIN32.  [ruby-core:16984]
+
+Wed May 28 18:05:28 2008  Akinori MUSHA  <knu at iDaemons.org>
+
+	* array.c (rb_ary_nitems, Init_Array): Axe Array#nitems().
+	  cf. [ruby-dev:34676]-[ruby-dev:34713]
+
+Wed May 28 17:50:32 2008  Nobuyoshi Nakada  <nobu at ruby-lang.org>
+
+	* win32/mkexports.rb (Exports#objdump, Exports#each_line): extracted.
+
+Wed May 28 17:41:43 2008  Nobuyoshi Nakada  <nobu at ruby-lang.org>
+
+	* Makefile.in (MKPREP): appended $(RBCONFIG).
+
+	* common.mk (enc.mk, prelude.c): not depend on $(RBCONFIG) on mswin32
+	  to get of compiling twice each time.
+
+	* win32/Makefile.sub (prelude.c): not depend on $(PREP).
+
+Wed May 28 17:37:07 2008  NAKAMURA Usaku  <usa at ruby-lang.org>
+
+	* win32/mkexports.rb (Exports::Mswin#each_export): speed up.
+
+Wed May 28 16:41:59 2008  Akinori MUSHA  <knu at iDaemons.org>
+
+	* array.c (rb_ary_slice_bang): Call rb_ary_modify_check() at the
+	  beginning. [rubyspec]
+
+Wed May 28 16:12:44 2008  Akinori MUSHA  <knu at iDaemons.org>
+
+	* lib/webrick/httpservlet/cgihandler.rb (WEBrick::HTTPServlet::CGIHandler#do_GET):
+	  Set the HTTP status code to 302 if a Location header field is
+	  present and the status code is not valid as a client
+	  redirection.  cf. RFC 3875 6.2.3, 6.2.4.
+
+Wed May 28 15:53:52 2008  NAKAMURA Usaku  <usa at ruby-lang.org>
+
+	* enc/trans/japanese.c (to_SHIFT_JIS_EF_infos): typo.
+
+Wed May 28 15:18:16 2008  Nobuyoshi Nakada  <nobu at ruby-lang.org>
+
+	* lib/singleton.rb (SingletonClassMethods): _load should be public.
+
+Wed May 28 13:30:43 2008  NARUSE, Yui  <naruse at ruby-lang.org>
+
+	* enc/trans/japanese.c: add workarround for Unicode to CP932.
+	  U+2015->0x815C, U+2225->0x8161, U+FF0D->0x817C, U+FF3C->0x815F,
+	  U+FF5E->0x8160, U+FFE0->0x8191, U+FFE1->0x8192, U+FFE2->0x81CA
+
+Wed May 28 12:52:41 2008  Nobuyoshi Nakada  <nobu at ruby-lang.org>
+
+	* marshal.c (w_object, marshal_dump, r_object0, marshal_load): search
+	  private methods too.  [ruby-dev:34671]
+
+	* object.c (convert_type): ditto.
+
+Wed May 28 08:42:51 2008  Tanaka Akira  <akr at fsij.org>
+
+	* numeric.c: "%" is required before PRI?VALUE.
+
+Tue May 27 22:10:44 2008  Nobuyoshi Nakada  <nobu at ruby-lang.org>
+
+	* eval_error.c (error_handle): SystemExit and SignalException throws
+	  TAG_RAISE but not TAG_FATAL.
+
+	* thread.c (rb_thread_execute_interrupts): delay interrupts during
+	  raising exceptions.  [ruby-dev:34855]
+
+Tue May 27 20:18:30 2008  Akinori MUSHA  <knu at iDaemons.org>
+
+	* array.c (rb_ary_slice_bang): Return an empty array instead of
+	  nil when pos is valid and len is adjusted from a valid value to
+	  zero; caught by RubySpec.
+
+Tue May 27 19:12:37 2008  Nobuyoshi Nakada  <nobu at ruby-lang.org>
+
+	* Makefile.in (MKPREP), common.mk, win32/Makefile.sub (prelude.c): get
+	  rid of depending PREP with nmake.
+
+	* common.mk (encs): depends on libruby.
+
+Tue May 27 19:00:22 2008  Akinori MUSHA  <knu at iDaemons.org>
+
+	* ext/stringio/stringio.c (strio_each_char, Init_stringio): Add
+	  StringIO#{each_char,chars}.
+	  (Init_stringio): Fix StringIO#bytes.
+
+Tue May 27 17:54:35 2008  Akinori MUSHA  <knu at iDaemons.org>
+
+	* ext/stringio/stringio.c (strio_each_byte): Return self instead
+	  of nil as the rdoc says.
+
+Tue May 27 15:36:27 2008  Yukihiro Matsumoto  <matz at ruby-lang.org>
+
+	* numeric.c (check_int): use PRIxVALUE format specifier.
+
+	* numeric.c (check_uint, rb_num2fix, int_chr): ditto.
+
+	* numeric.c (num_fdiv): fallback to_f should always return float
+	  result.  should not use #quo that may return rational.
+
+	* numeric.c (num_div): should raise ZeroDivisionError.
+
+	* numeric.c (fix_divide): ditto.
+
+	* test/ruby/test_numeric.rb (TestNumeric::test_divmod): avoid
+	  ZeroDivisionError in tests.
+
+Tue May 27 13:14:53 2008  Akinori MUSHA  <knu at iDaemons.org>
+
+	* enum.c (enum_to_a): Pass arguments through to #each().
+	  (enum_sort): Follow the enum_to_a signature change.
+	  (enum_reverse_each): Add #reverse_each().
+
+Tue May 27 13:12:37 2008  Akinori MUSHA  <knu at iDaemons.org>
+
+	* io.c (Init_IO): Define ARGF.{lines,bytes,chars}.
+
+Tue May 27 12:06:37 2008  NAKAMURA Usaku  <usa at ruby-lang.org>
+
+	* file.c (BUFCHECK): wrong condition. [ruby-core:16921]
+
+	* file.c (file_expand_buf): shouldn't use buflen for length of string.
+
+Mon May 26 18:24:48 2008  Nobuyoshi Nakada  <nobu at ruby-lang.org>
+
+	* file.c (BUFCHECK): no resize if enough room.
+
+	* file.c (file_expand_path): use BUFCHECK.
+
+Mon May 26 17:48:42 2008  Akinori MUSHA  <knu at iDaemons.org>
+
+	* enumerator.c (struct enumerator, enumerator_init)
+	  (enumerator_init_copy, enumerator_each): Eliminate iter.
+	  (enumerator_ptr): Do not hardcode the class name.
+	  (enumerator_with_index): Delay variable initialization after
+	  RETURN_ENUMERATOR().
+
+Mon May 26 17:23:49 2008  NAKAMURA Usaku  <usa at ruby-lang.org>
+
+	* file.c (file_expand_path): add more space for '/'.
+
+	* file.c (file_expand_path): should reset address of p after calling
+	  rb_str_resize(). [ruby-dev:34800]
+
+Mon May 26 16:49:55 2008  Yukihiro Matsumoto  <matz at ruby-lang.org>
+
+	* misc/ruby-mode.el (ruby-mode): use run-hooks if run-mode-hook is
+	  not available.  a patch from Kazuhiro NISHIYAMA <zn at mbf.nifty.com>
+	  in [ruby-dev:34853].
+
+Mon May 26 16:41:35 2008  NAKAMURA Usaku  <usa at ruby-lang.org>
+
+	* file.c (ntfs_tail): filename which starts with '.' is valid.
+
+	* file.c (file_expand_path): cygwin symlink support.
+
+Mon May 26 07:15:52 2008  Nobuyoshi Nakada  <nobu at ruby-lang.org>
+
+	* vm_dump.c (rb_vm_bugreport): rb_make_backtrace has no arguments.
+
+Mon May 26 01:17:54 2008  Tanaka Akira  <akr at fsij.org>
+
+	* test/ruby/envutil.rb (assert_normal_exit): signal description
+	  refined.
+
+Mon May 26 00:52:52 2008  Akinori MUSHA  <knu at iDaemons.org>
+
+	* hash.c (env_each_key, env_each_value, env_reject_bang)
+	  (rb_env_clear, env_replace): Omit duplicated secure level check.
+
+Mon May 26 00:37:16 2008  Akinori MUSHA  <knu at iDaemons.org>
+
+	* hash.c (env_each_value): Do not call env_values() twice.
+
+Sun May 25 17:54:36 2008  Yusuke Endoh  <mame at tsg.ne.jp>
+
+	* compile.c (iseq_compile): set local_table for
+	  ISEQ_TYPE_DEFINED_GUARD.
+
+Sun May 25 17:52:25 2008  Yusuke Endoh  <mame at tsg.ne.jp>
+
+	* compile.c (iseq_build_body): remove side effect from
+	  VM::InstructionSequence.load.
+
+Sun May 25 04:30:45 2008  Yusuke Endoh  <mame at tsg.ne.jp>
+
+	* test/ruby/test_modules.rb (remove_json_mixins): change judgment
+	  condition.
+
+Sun May 25 03:54:39 2008  Yusuke Endoh  <mame at tsg.ne.jp>
+
+	* test/ruby/test_modules.rb (test_ancestors, test_included_modules):
+	  ignore json mixins.
+
+Sun May 25 02:37:25 2008  Koichi Sasada  <ko1 at atdot.net>
+
+	* eval_method.c: renamed from vm_method.c.  "vm_method.c" is included
+	  by "vm.c".
+
+	* vm_eval.c: added.  Some codes are moved from "eval.c"
+
+	* common.mk: fix for above changes.
+
+	* compile.c: make a vm_eval(0)
+
+	* eval.c, eval_error.c, eval_intern.h, eval_jump.c, proc.c, vm.c,
+	  id.c, id.h, vm_core.h, vm_dump.c, vm_evalbody.c, vm_insnhelper.c,
+	  blockinlining.c: fix for above changes.  and do some refactoring.
+	  this changes improve rb_yield() performance.
+
+Sat May 24 22:32:49 2008  Yukihiro Matsumoto  <matz at ruby-lang.org>
+
+	* util.c (ruby_strtod): clear errno at the top of our own
+	  impelementation of strtod(3).  [ruby-dev:34834] [ruby-dev:34839]
+
+Sat May 24 15:26:16 2008  Yusuke Endoh  <mame at tsg.ne.jp>
+
+	* compile.c (iseq_set_exception_table, NODE_WHILE, NODE_NEXT): remove
+	  special handling that decrements sp in CATCH_TYPE_NEXT for NODE_WHILE.
+
+	* vm.c (vm_eval_body), vm_insnhelper.c (vm_throw): remove unused code.
+
+Sat May 24 08:13:34 2008  NARUSE, Yui  <naruse at ruby-lang.org>
+
+	* transcode.c (rb_str_transcode): argc is 1, and argv is &to.
+
+Fri May 23 17:55:11 2008  Akinori MUSHA  <knu at iDaemons.org>
+
+	* array.c (rb_ary_slice_bang): Be consistent with Array#slice()
+	  and String#slice!().  Just return nil when a negative length or
+	  out of boundary index is given instead of raising an exception
+	  via internal functions.
+
+Fri May 23 16:44:34 2008  Akinori MUSHA  <knu at iDaemons.org>
+
+	* enumerator.c (Init_Enumerator): Override
+	  Enumerable::Enumerator#each_with_index with #with_index.
+
+Fri May 23 12:23:05 2008  Nobuyoshi Nakada  <nobu at ruby-lang.org>
+
+	* vm_core.h (rb_num_t): moved form vm.h.
+
+	* tool/instruction.rb (RubyVM::Instruction#sp_increase_c_expr),
+	  tool/instruction.rb (RubyVM::VmBodyGenerator#make_header_operands):
+	  omit unused variables.
+
+Fri May 23 08:47:02 2008  Yukihiro Matsumoto  <matz at ruby-lang.org>
+
+	* error.c (exc_equal): == operator should be transitional.  
+	  [ruby-dev:34808]
+
+	* error.c (syserr_eqq): === should be able to handle delegated
+	  objects as well.
+
+Fri May 23 06:15:20 2008  Nobuyoshi Nakada  <nobu at ruby-lang.org>
+
+	* iseq.c (rb_iseq_compile_with_option): get rid of segv.
+
+Fri May 23 02:29:14 2008  Koichi Sasada  <ko1 at atdot.net>
+
+	* insns.def (opt_gt|ge|lt|le): use values directly to compare.
+
+Fri May 23 01:15:09 2008  Koichi Sasada  <ko1 at atdot.net>
+
+	* eval.c, eval_intern.h, include/ruby/intern.h, include/ruby/ruby.h,
+	  vm.c, vm_core.h, vm_insnhelper.c: remove pointless "const".
+
+Thu May 22 23:45:17 2008  Yusuke Endoh  <mame at tsg.ne.jp>
+
+	* compile.c (get_destination_insn, get_next_insn, get_prev_insn):
+	  peephole optimization should not ignore ISEQ_ELEMENT_ADJUST.
+
+Thu May 22 20:20:54 2008  Nobuyoshi Nakada  <nobu at ruby-lang.org>
+
+	* marshal.c (check_dump_arg, check_load_arg): check if reentered.
+	  [ruby-dev:34802]
+
+Thu May 22 20:14:28 2008  Yusuke Endoh  <mame at tsg.ne.jp>
+
+	* iseq.c (iseq_load, iseq_data_to_ary): support
+	  ISEQ_TYPE_DEFINED_GUARD.
+
+Thu May 22 19:01:29 2008  Nobuyoshi Nakada  <nobu at ruby-lang.org>
+
+	* vm.c (vm_get_ruby_level_cfp): moved from eval_intern.h.
+
+	* vm.c (sdr, nsdr): define methods only if VMDEBUG is defined.
+
+Thu May 22 17:18:35 2008  Tanaka Akira  <akr at fsij.org>
+
+	* array.c (rb_ary_compact_bang): fix reallocation size.
+
+Thu May 22 15:20:20 2008  NAKAMURA Usaku  <usa at ruby-lang.org>
+
+	* eval_intern.h, vm_core.h, include/ruby/intern.h, include/ruby/ruby.h,
+	  vm.c: need to add const to prototypes, of course.
+
+Thu May 22 13:24:43 2008  Koichi Sasada  <ko1 at atdot.net>
+
+	* eval.c, vm.c, vm_core.h, vm_insnhelper.c: specify "const".
+
+	* vm_opts.h: add a OPT_TOKEN_THREADED_CODE macro.
+
+Thu May 22 12:51:41 2008  Tanaka Akira  <akr at fsij.org>
+
+	* insns.def (newhash): fix a variable definition: "const k".
+
+Thu May 22 12:40:54 2008  Nobuyoshi Nakada  <nobu at ruby-lang.org>
+
+	* array.c (flatten): check if reentered.  [ruby-dev:34798]
+
+Thu May 22 11:39:59 2008  Tanaka Akira  <akr at fsij.org>
+
+	* test/ruby/envutil.rb (assert_normal_exit): capture stdout and stderr
+	  of the child process.
+
+Thu May 22 08:28:49 2008  Yukihiro Matsumoto  <matz at ruby-lang.org>
+
+	* array.c (flatten): free memo hash table before raising exception.
+	  [ruby-dev:34789]
+
+Thu May 22 06:30:10 2008  Hidetoshi NAGAI  <nagai at ai.kyutech.ac.jp>
+
+	* array.c (flatten): fix memory leak.
+
+Thu May 22 06:21:34 2008  NARUSE, Yui  <naruse at ruby-lang.org>
+
+	* ext/nkf/nkf-utf8/nkf.c (nkf_str_caseeql): added.
+
+	* ext/nkf/nkf-utf8/nkf.c (nkf_enc_find_index): use nkf_str_caseeql.
+
+Thu May 22 05:45:30 2008  Yukihiro Matsumoto  <matz at ruby-lang.org>
+
+	* proc.c (proc_dup): should copy safe_level from src proc
+	  properly.  a patch from Keita Yamaguchi
+	  <keita.yamaguchi at gmail.com>
+
+Thu May 22 02:46:08 2008  Shugo Maeda  <shugo at ruby-lang.org>
+
+	* lib/net/imap.rb: do not use Thread#raise. [ruby-dev:34739]
+
+Thu May 22 00:30:06 2008  Yusuke Endoh  <mame at tsg.ne.jp>
+
+	* test/ruby/test_require.rb: new tests for library requiring, to
+	  achieve over 90% test coverage of dln.c.
+
+	* test/ruby/test_class.rb: add tests to achieve over 90% test coverage
+	  of class.c.
+
+	* test/ruby/test_module.rb: ditto.
+
+Thu May 22 00:15:44 2008  Koichi Sasada  <ko1 at atdot.net>
+
+	* insns.def, vm_insnhelper.c: specify "const".
+
+Wed May 21 23:20:21 2008  Koichi Sasada  <ko1 at atdot.net>
+
+	* bootstraptest/test_eval.rb: fix syntax.
+
+Wed May 21 17:46:17 2008  NARUSE, Yui  <naruse at ruby-lang.org>
+
+	* ext/nkf/nkf-utf8/nkf.c (nkf_enc_find_index):
+	  use strcasecmp. [ruby-dev:34787]
+
+Wed May 21 16:48:22 2008  Yukihiro Matsumoto  <matz at ruby-lang.org>
+
+	* array.c (rb_ary_compact_bang): avoid forceful realloc.
+
+Wed May 21 07:42:28 2008  NARUSE, Yui  <naruse at ruby-lang.org>
+
+	* string.c (rb_usascii_str_new): use rb_str_new.
+
+	* string.c (rb_enc_str_new): ditto.
+
+	* string.c (rb_usascii_str_new2): use rb_str_new2.
+
+Wed May 21 07:22:01 2008  NARUSE, Yui  <naruse at ruby-lang.org>
+
+	* encoding.c, include/ruby/encoding.h
+	  (rb_enc_associate, rb_enc_associate_index):
+	  returns obj. [ruby-dev:34778]
+
+Wed May 21 04:20:20 2008  NARUSE, Yui  <naruse at ruby-lang.org>
+
+	* encoding.c (rb_ascii8bit_encoding): use ENCINDEX_ASCII.
+
+	* encoding.c, include/ruby/encoding.h (rb_ascii8bit_encindex):
+	  added.
+
+	* encoding.c (rb_locale_encoding): use rb_usascii_encoding().
+
+Wed May 21 01:45:58 2008  NAKAMURA Usaku  <usa at ruby-lang.org>
+
+	* test/ruby/test_file_exhaustive.rb (setup): workaround for Windows
+	  Vista.
+
+	* test/ruby/envutil.rb (rubyexec): now Open3.open3 is supported on
+	  Windows.
+
+	* test/ruby/test_process.rb: use ``||'' instead of ``;'' because
+	  cmd.exe not support it.
+
+Wed May 21 01:28:47 2008  NARUSE, Yui  <naruse at ruby-lang.org>
+
+	* transcode.c, include/ruby/encodng.h (rb_str_transcode):
+	  C API of encoding conversion for Ruby object.
+	  VALUE rb_str_transcode(VALUE str, VALUE to).
+
+	* transcode.c (str_encode, str_encode_bang):
+	  rename from rb_tr_transcode or rb_str_transcode_bang.
+
+Tue May 20 23:26:05 2008  Yusuke Endoh	<mame at tsg.ne.jp>
+
+	* test/ruby/test_array.rb: fix tests for 64bit CPU.
+
+Tue May 20 20:59:56 2008  NARUSE, Yui  <naruse at ruby-lang.org>
+
+	* ext/nkf/nkf-utf8/nkf.c (rb_nkf_convert) (nkf_enc_without_bom):
+	  reverted. nkf-utf8/nkf.c should be independent of ruby.
+
+	* ext/nkf/nkf.c (options):
+	  moved from nkf-utf8/nkf.c. 
+	  override nkf's original settings for Unicode BOM.
+
+Tue May 20 13:20:51 2008  Nobuyoshi Nakada  <nobu at ruby-lang.org>
+
+	* ext/nkf/nkf.c (rb_nkf_convert), ext/nkf/nkf-utf8/nkf.c
+	  (nkf_enc_without_bom): BOM is not a part of encodings.
+
+	* ext/nkf/nkf.c (Init_nkf), ext/nkf/nkf-utf8/nkf.c (options):
+	  UTF-{16,32} without endian have no sense.
+
+Tue May 20 12:13:50 2008  Nobuyoshi Nakada  <nobu at ruby-lang.org>
+
+	* ruby.c (proc_options, process_options): --dump option.
+
+Tue May 20 11:36:06 2008  Nobuyoshi Nakada  <nobu at ruby-lang.org>
+
+	* include/ruby/ruby.h (PRI[diouxX]VALUE): printf format for VALUE.
+
+	* gc.c (assign_heap_slot): suppress a warning.
+
+Tue May 20 03:42:43 2008  Koichi Sasada  <ko1 at atdot.net>
+
+	* eval.c, vm_insnhelper.c: fix cref in instance_eval
+	  and cvar_base search protocol.
+
+	* bootstraptest/test_knownbug.rb, test_eval.rb: move soleved test
+	  and add new tests.
+
+	* test/ruby/test_eval.rb: fix tests for spec.
+
+Tue May 20 01:43:44 2008  Koichi Sasada  <ko1 at atdot.net>
+
+	* bootstraptest/test_knownbug.rb: fix a test.
+	  "block_given?" returns true if "yield" can be used.
+
+Tue May 20 01:07:19 2008  Yusuke Endoh  <mame at tsg.ne.jp>
+
+	* parse.y (assignable_gen): when "self = 1" was evalueted, unnecessary
+	  error message was output, which might cause null pointer access.
+
+Tue May 20 08:38:56 2008  Yukihiro Matsumoto  <matz at ruby-lang.org>
+
+	* string.c (rb_enc_strlen_cr): need to set ENC_CODERANGE_7BIT if
+	  search_nonascii() fails.    [ruby-dev:34751]
+
+	* string.c (rb_str_reverse): preserve coderange info if the
+	  receiver is 7bit string.
+
+	* string.c (rb_str_reverse_bang): ditto.
+
+	* string.c (rb_str_reverse_bang): should have called
+	  single_byte_optimizable before rb_str_modify() that clears
+	  coderange info.
+
+	* string.c (tr_trans): handle single bytes more eagerly.
+
+Mon May 19 23:32:12 2008  Koichi Sasada  <ko1 at atdot.net>
+
+	* vm.c (invoke_block_from_c): fix call flow.
+
+Mon May 19 23:19:35 2008  Yusuke Endoh  <mame at tsg.ne.jp>
+
+	* regexec.c (slow_search): check the case when the length is 1.
+	  The behavior of memcmp is undefined if the third argument is 0.
+
+Mon May 19 21:07:48 2008  Koichi Sasada  <ko1 at atdot.net>
+
+	* thread_pthread.c (native_thread_apply_priority): 
+	  fix argument range check.  [ruby-dev:33124]
+
+Mon May 19 18:22:35 2008  Akinori MUSHA  <knu at iDaemons.org>
+
+	* ext/openssl/ossl_pkcs5.c (ossl_pkcs5_pbkdf2_hmac): Fix the type
+	  of md; pointed out by Takahiro Kambe <taca at back-street.net>
+	  in [ruby-dev:34748].
+
+Mon May 19 17:23:55 2008  Yukihiro Matsumoto  <matz at ruby-lang.org>
+
+	* regparse.c (PINC): use optimized enclen() instead of
+	  ONIGENC_MBC_ENC_LEN().
+
+	* regparse.c (PFETCH): ditto.
+
+	* regparse.c (PFETCH): small optimization.
+
+	* regexec.c (slow_search): single byte encoding optimization.
+
+	* regenc.h (enclen): avoid calling function when encoding's
+	  min_len == max_len.
+
+	* re.c (rb_reg_regsub): rb_enc_ascget() optimization for single
+	  byte encoding.
+
+	* re.c (rb_reg_search): avoid allocating new re_registers if we
+	  already have MatchData.
+
+	* re.c (match_init_copy): avoid unnecessary onig_region_free()
+	  before onig_region_copy. 
+
+	* encoding.c (rb_enc_get_index): remove implicit enc_capable check
+	  each time.
+
+	* encoding.c (rb_enc_set_index): ditto.
+
+	* encoding.c (enc_compatible_p): small refactoring.
+
+	* include/ruby/encoding.h (rb_enc_dummy_p): inline
+	  rb_enc_dummy_p() and export related code.
+
+Mon May 19 14:32:03 2008  Koichi Sasada  <ko1 at atdot.net>
+
+	* version.h: fix strange change by version.h update tool.
+
+Mon May 19 14:18:13 2008  Koichi Sasada  <ko1 at atdot.net>
+
+	* bootstraptest/test_knownbug.rb: move solved tests.
+
+	* bootstraptest/test_eval.rb, test_literal.rb, test_syntax.rb,
+	  test_thread.rb: ditto.
+
+	* test/ruby/test_m17n.rb, test_proc.rb, test_sprintf.rb,
+	  test_string.rb, test/ruby/test_struct.rb: ditto.
+
+Mon May 19 13:23:03 2008  NAKAMURA Usaku  <usa at ruby-lang.org>
+
+	* process.c (rb_spawn_internal): set last_status when status == -1
+	  because there is no path to set it on win32. this patch is derived
+	  from [ruby-core:16787], submitted by Luis Lavena <luislavena at
+	  gmail.com>
+
+Mon May 19 11:32:47 2008  Koichi Sasada  <ko1 at atdot.net>
+
+	* vm.c, insns.def, eval.c, vm_insnhelper.c: fix CREF handling.
+	  VM value stack frame of block contains cref information.
+	 (dfp[-1] points CREF)
+
+	* compile.c, eval_intern.h, eval_method.c, load.c, proc.c,
+	  vm_dump.h, vm_core.h: ditto.
+
+	* include/ruby/ruby.h, gc.c: remove T_VALUES because of above
+	  changes.
+
+	* bootstraptest/test_eval.rb, test_knownbug.rb: move solved test.
+
+Sun May 18 22:26:51 2008  GOTOU Yuuzou  <gotoyuzo at notwork.org>
+
+	* lib/webrick/httpservlet/filehandler.rb: should normalize path
+	  name in path_info to prevent script disclosure vulnerability on
+	  DOSISH filesystems. (fix: CVE-2008-1891)
+	  Note: NTFS/FAT filesystem should not be published by the platforms
+	  other than Windows. Pathname interpretation (including short
+	  filename) is less than perfect.
+
+	* lib/webrick/httpservlet/abstract.rb
+	  (WEBrick::HTTPServlet::AbstracServlet#redirect_to_directory_uri):
+	  should escape the value of Location: header.
+
+	* lib/webrick/httpservlet/cgi_runner.rb: accept interpreter
+	  command line arguments.
+
+Sun May 18 02:54:46 2008  Yusuke Endoh  <mame at tsg.ne.jp>
+
+	* pack.c (pack_pack): check errno to detect error of ruby_strtoul.
+
+	* pack.c (pack_unpack): ditto.
+
+	* test/ruby/test_pack.rb: add a test for above.
+
+Sat May 17 23:53:57 2008  Nobuyoshi Nakada  <nobu at ruby-lang.org>
+
+	* file.c (file_expand_path): fix for short file name on Cygwin.
+
+Sat May 17 18:03:52 2008  Yuki Sonoda (Yugui) <yugui at yugui.jp>
+
+	* vm.c (Init_VM): removed the definition of Thread#initialize,
+	  which is overwritten in Init_Thread and is never used.
+
+Sat May 17 14:01:50 2008  Nobuyoshi Nakada  <nobu at ruby-lang.org>
+
+	* array.c (rb_ary_sort_bang): should not free shared pointer, and set
+	  shared.  [ruby-dev:34732]
+
+Sat May 17 12:34:54 2008  Yuki Sonoda (Yugui) <yugui at yugui.jp>
+
+	* thread_pthread.c (Init_native_thread): Kernel#.sleep used never to
+	  sleep on Mac OS X. Reported by arton <artonx AT yahoo.co.jp>.
+
+	* thread_pthread.c (native_sleep): added error checks.
+
+Sat May 17 11:29:11 2008  Nobuyoshi Nakada  <nobu at ruby-lang.org>
+
+	* file.c (rb_file_s_extname): first dot is not an extension name.
+
 Sat May 17 03:21:29 2008  Yukihiro Matsumoto  <matz at ruby-lang.org>
 
 	* array.c (rb_ary_sort_bang): stop memory leak.  [ruby-dev:34726]
@@ -68,7 +962,7 @@
 
 Thu May 15 12:19:42 2008  Yukihiro Matsumoto  <matz at ruby-lang.org>
 
-	* ext/openssl/openssl_missing.c (HMAC_CTX_copy): adopted to
+	* ext/openssl/openssl_missing.c (HMAC_CTX_copy): adopted
 	  prototype change in openssl bundled with newer OpenBSD.
 	  a patch from Takahiro Kambe <taca at back-street.net> in
 	  [ruby-dev:34691].
@@ -165,7 +1059,7 @@
 
 Tue May 13 08:25:31 2008  Tanaka Akira  <akr at fsij.org>
 
-	* io.c (rb_f_gets.): re-enable rdoc.
+	* io.c (rb_f_gets): re-enable rdoc.
 	  (rb_f_readline): ditto.
 	  (rb_f_readlines): ditto.
 
@@ -21629,7 +22523,7 @@
 Mon Jul 18 00:43:05 2006  Nobuyoshi Nakada  <nobu at ruby-lang.org>
 
 	* util.c (ruby_strtod): stop at dot not followed by digits.
-	  fixed: [ruby-dev:29035]
+	  fixed: [ruby-dev:29036]
 
 Tue Jul 18 00:01:27 2006  Nobuyoshi Nakada  <nobu at ruby-lang.org>
 

Modified: MacRuby/branches/testing/Makefile.in
===================================================================
--- MacRuby/branches/testing/Makefile.in	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/Makefile.in	2008-06-05 08:33:02 UTC (rev 249)
@@ -42,6 +42,7 @@
 cflags = @cflags@
 optflags = @optflags@
 debugflags = @debugflags@
+warnflags = @warnflags@
 XCFLAGS = -I. -I$(arch_hdrdir) -I$(hdrdir) -I$(srcdir) @XCFLAGS@
 CPPFLAGS = @CPPFLAGS@
 LDFLAGS = @STATIC@ $(CFLAGS) @LDFLAGS@
@@ -96,7 +97,7 @@
 AS            = @AS@
 ASFLAGS       = @ASFLAGS@
 IFCHANGE      = $(srcdir)/tool/ifchange
-SET_LC_MESSAGES = LC_MESSAGES=C
+SET_LC_MESSAGES = env LC_MESSAGES=C
 
 OBJEXT        = @OBJEXT@
 ASMEXT        = S

Modified: MacRuby/branches/testing/README
===================================================================
--- MacRuby/branches/testing/README	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/README	2008-06-05 08:33:02 UTC (rev 249)
@@ -65,6 +65,10 @@
 
   2. Run ./configure, which will generate config.h and Makefile.
 
+     Some C compiler flags may be added by default depending on your
+     environment.  Specify optflags=.. and warnflags=.. as necessary
+     to override them.
+
   3. Edit defines.h if you need.  Usually this step will not be needed.
 
   4. Remove comment mark(#) before the module names from ext/Setup (or

Modified: MacRuby/branches/testing/README.ja
===================================================================
--- MacRuby/branches/testing/README.ja	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/README.ja	2008-06-05 08:33:02 UTC (rev 249)
@@ -88,6 +88,10 @@
 
   2. configure\xA4\xF2\xBC¹Ԥ\xB7\xA4\xC6Makefile\xA4ʤɤ\xF2\xC0\xB8\xC0\xAE\xA4\xB9\xA4\xEB
 
+     \xB4Ķ\xAD\xA4ˤ\xE8\xA4äƤϥǥե\xA9\xA5\xEB\xA5Ȥ\xCEC\xA5\xB3\xA5\xF3\xA5ѥ\xA4\xA5\xE9\xCDѥ\xAA\xA5ץ\xB7\xA5\xE7\xA5\xF3\xA4\xAC\xC9դ\xAD
+     \xA4ޤ\xB9\xA1\xA5configure\xA5\xAA\xA5ץ\xB7\xA5\xE7\xA5\xF3\xA4\xC7 optflags=.. warnflags=.. \xC5\xF9
+     \xA4Ǿ\xE5\xBD��Ǥ\xAD\xA4ޤ\xB9\xA1\xA5
+
   3. (ɬ\xCDפʤ\xE9\xA4\xD0)defines.h\xA4\xF2\xCAԽ\xB8\xA4\xB9\xA4\xEB
 
      ¿ʬ\xA1\xA4ɬ\xCD\xD7̵\xA4\xA4\xA4Ȼפ\xA4\xA4ޤ\xB9\xA1\xA5

Modified: MacRuby/branches/testing/array.c
===================================================================
--- MacRuby/branches/testing/array.c	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/array.c	2008-06-05 08:33:02 UTC (rev 249)
@@ -44,7 +44,6 @@
 #if WITH_OBJC
 /* TODO optimize this */
 struct rb_objc_ary_struct {
-    bool named_args;
     void *cptr;
 };
 
@@ -66,7 +65,6 @@
     if (s == NULL) {
 	s = xmalloc(sizeof(struct rb_objc_ary_struct));
 	rb_objc_set_associative_ref((void *)ary, &rb_objc_ary_assoc_key, s);
-	s->named_args = false;
 	s->cptr = NULL;
     }
     return s;
@@ -93,7 +91,7 @@
 rb_ary_modify_check(VALUE ary)
 {
     long mask;
-    mask = rb_objc_flag_get_mask(ary);
+    mask = rb_objc_flag_get_mask((void *)ary);
     if (mask == 0) {
 	bool _CFArrayIsMutable(void *);
 	if (!_CFArrayIsMutable((void *)ary))
@@ -413,7 +411,7 @@
     VALUE size, val;
 
     rb_ary_modify(ary);
-    if (rb_scan_args(argc, argv, "02", &size, &val) == 0) {
+    if (argc ==  0) {
 #if !WITH_OBJC
 	if (RARRAY_PTR(ary) && !ARY_SHARED_P(ary)) {
 	    free(RARRAY(ary)->ptr);
@@ -425,7 +423,7 @@
 	}
 	return ary;
     }
-
+    rb_scan_args(argc, argv, "02", &size, &val);
     if (argc == 1 && !FIXNUM_P(size)) {
 	val = rb_check_array_type(size);
 	if (!NIL_P(val)) {
@@ -452,7 +450,7 @@
 	    rb_warn("block supersedes default value argument");
 	}
 	for (i=0; i<len; i++) {
-	    rb_ary_insert(ary, i, rb_yield(LONG2NUM(i)));
+	    rb_ary_store(ary, i, rb_yield(LONG2NUM(i)));
 #if !WITH_OBJC
 	    RARRAY(ary)->len = i + 1;
 #endif
@@ -795,7 +793,6 @@
 rb_ary_shift_m(int argc, VALUE *argv, VALUE ary)
 {
     VALUE result;
-    long n;
 
     if (argc == 0) {
 	return rb_ary_shift(ary);
@@ -833,8 +830,6 @@
 static VALUE
 rb_ary_unshift_m(int argc, VALUE *argv, VALUE ary)
 {
-    long len;
-
     if (argc == 0) return ary;
     rb_ary_modify(ary);
 #if WITH_OBJC
@@ -1231,7 +1226,7 @@
    
     i = n = RARRAY_LEN(ary);
 
-    if (rb_scan_args(argc, argv, "01", &val) == 0) {
+    if (argc == 0) {
 	RETURN_ENUMERATOR(ary, 0, 0);
 	while (i--) {
 	    if (RTEST(rb_yield(RARRAY_AT(ary, i))))
@@ -1242,6 +1237,7 @@
 	}
     }
     else {
+ 	rb_scan_args(argc, argv, "01", &val);
 #if WITH_OBJC
 	i = CFArrayGetLastIndexOfValue((CFArrayRef)ary, CFRangeMake(0, n),
 	   (const void *)val);
@@ -1586,9 +1582,6 @@
 {
 #if WITH_OBJC
     VALUE dup = rb_ary_dup2(ary);
-    /* copy the named_args flag, but not other flags */
-    if (rb_ary_is_named_args(ary))
-	rb_ary_set_named_args(dup, true);
 #else
     VALUE dup = rb_ary_new2(RARRAY_LEN(ary));
 
@@ -1614,7 +1607,7 @@
 VALUE
 rb_ary_join(VALUE ary, VALUE sep)
 {
-    long len = 1, i, count;
+    long i, count;
     int taint = Qfalse;
     VALUE result, tmp;
 
@@ -1883,18 +1876,39 @@
  *     a.sort {|x,y| y <=> x }   #=> ["e", "d", "c", "b", "a"]
  */
 
+#if WITH_OBJC
+static void
+rb_ary_sort_bang1(VALUE ary, bool is_dup)
+{
+    long n = RARRAY_LEN(ary);
+    if (n > 1) {
+	if (rb_block_given_p()) {
+	    VALUE tmp = is_dup ? ary : rb_ary_dup(ary);
+	    CFArraySortValues((CFMutableArrayRef)tmp,
+		    CFRangeMake(0, n),
+		    (CFComparatorFunction)sort_1,
+		    NULL);
+	    if (!is_dup)
+		rb_ary_replace(ary, tmp);
+	}
+	else {
+	    CFArraySortValues((CFMutableArrayRef)ary,
+		    CFRangeMake(0, n),
+		    (CFComparatorFunction)sort_2,
+		    NULL);
+	}
+    }
+}
+#endif
+
 VALUE
 rb_ary_sort_bang(VALUE ary)
 {
-    long n = RARRAY_LEN(ary);
     rb_ary_modify(ary);
-    if (n > 1) {
 #if WITH_OBJC
-	CFArraySortValues((CFMutableArrayRef)ary,
-	    CFRangeMake(0, n),
-	    (CFComparatorFunction)(rb_block_given_p() ? sort_1 : sort_2),
-	    NULL);
+    rb_ary_sort_bang1(ary, false);
 #else
+    if (RARRAY_LEN(ary) > 1) {
 	VALUE tmp = ary_make_shared(ary);
 
 	RBASIC(tmp)->klass = 0;
@@ -1911,8 +1925,8 @@
 	RARRAY(tmp)->len = 0;
 	RARRAY(tmp)->aux.capa = 0;
 	RBASIC(tmp)->klass = RBASIC(ary)->klass;
+    }
 #endif
-    }
     return ary;
 }
 
@@ -1936,7 +1950,7 @@
 rb_ary_sort(VALUE ary)
 {
     ary = rb_ary_dup(ary);
-    rb_ary_sort_bang(ary);
+    rb_ary_sort_bang1(ary, true);
     return ary;
 }
 
@@ -2221,6 +2235,7 @@
     long pos, len;
     long alen;
 
+    rb_ary_modify_check(ary);
     alen = RARRAY_LEN(ary);
     if (rb_scan_args(argc, argv, "11", &arg1, &arg2) == 2) {
 	pos = NUM2LONG(arg1);
@@ -2338,6 +2353,7 @@
 static VALUE
 rb_ary_delete_if(VALUE ary)
 {
+    RETURN_ENUMERATOR(ary, 0, 0);
     rb_ary_reject_bang(ary);
     return ary;
 }
@@ -2473,9 +2489,6 @@
 VALUE
 rb_ary_replace(VALUE copy, VALUE orig)
 {
-    VALUE shared;
-    VALUE *ptr;
-
     orig = to_ary(orig);
     rb_ary_modify_check(copy);
     if (copy == orig) return copy;
@@ -2553,7 +2566,6 @@
 {
     VALUE item, arg1, arg2;
     long beg = 0, end = 0, len = 0, n;
-    VALUE *p, *pend;
     int block_p = Qfalse;
 
     n = RARRAY_LEN(ary);
@@ -2644,7 +2656,6 @@
 rb_ary_plus(VALUE x, VALUE y)
 {
     VALUE z;
-    long len;
 
 #if WITH_OBJC
     y = to_ary(y);
@@ -3299,45 +3310,60 @@
 
 /*
  *  call-seq:
- *     array.nitems -> int
- *     array.nitems { |item| block }  -> int
+ *     array.count      -> int
+ *     array.count(obj) -> int
+ *     array.count { |item| block }  -> int
  *  
- *  Returns the number of non-<code>nil</code> elements in _self_.
- *  If a block is given, the elements yielding a true value are
- *  counted.
+ *  Returns the number of elements.  If an argument is given, counts
+ *  the number of elements which equals to <i>obj</i>.  If a block is
+ *  given, counts the number of elements yielding a true value.
  *
- *  May be zero.
- *     
- *     [ 1, nil, 3, nil, 5 ].nitems   #=> 3
- *     [5,6,7,8,9].nitems { |x| x % 2 != 0 }  #=> 3
+ *     ary = [1, 2, 4, 2]
+ *     ary.count             # => 4
+ *     ary.count(2)          # => 2
+ *     ary.count{|x|x%2==0}  # => 3
+ *
  */
 
 static VALUE
-rb_ary_nitems(VALUE ary)
+rb_ary_count(int argc, VALUE *argv, VALUE ary)
 {
     long n = 0;
  
-    if (rb_block_given_p()) {
-	long i;
+    if (argc == 0) {
+	long i, count = RARRAY_LEN(ary);
 
-	for (i=0; i<RARRAY_LEN(ary); i++) {
-	    VALUE v = RARRAY_AT(ary, i);
- 	    if (RTEST(rb_yield(v))) n++;
- 	}
+	if (!rb_block_given_p())
+	    return LONG2NUM(count);
+
+#if WITH_OBJC
+	for (i = 0; i < count; i++) {
+	    if (RTEST(rb_yield(RARRAY_AT(ary, i)))) 
+		n++;
+	}
+#else
+	for (p = RARRAY_PTR(ary), pend = p + RARRAY_LEN(ary); p < pend; p++) {
+	    if (RTEST(rb_yield(*p))) n++;
+	}
+#endif
     }
     else {
+	VALUE obj;
+	long i, count = RARRAY_LEN(ary);
+
+	rb_scan_args(argc, argv, "1", &obj);
+	if (rb_block_given_p()) {
+	    rb_warn("given block not used");
+	}
 #if WITH_OBJC
-	long total = RARRAY_LEN(ary);
-	n = total - CFArrayGetCountOfValue((CFArrayRef)ary, 
-	    CFRangeMake(0, total), (const void *)Qnil);
+	for (i = 0; i < count; i++) {
+	    if (rb_equal(RARRAY_AT(ary, i), obj)) 
+		n++;
+	}
 #else
-	VALUE *p = RARRAY_PTR(ary);
-	VALUE *pend = p + RARRAY_LEN(ary);
-
- 	while (p < pend) {
- 	    if (!NIL_P(*p)) n++;
- 	    p++;
- 	}
+	for (p = RARRAY_PTR(ary), pend = p + RARRAY_LEN(ary); p < pend; p++) {
+	    if (rb_equal(*p, obj)) n++;
+	}
 #endif
     }
 
@@ -3362,6 +3388,11 @@
 	while (i < RARRAY_LEN(ary)) {
 	    elt = RARRAY_AT(ary, i++);
 	    tmp = rb_check_array_type(elt);
+#if !WITH_OBJC
+	    if (RBASIC(result)->klass) {
+		rb_raise(rb_eRuntimeError, "flatten reentered");
+	    }
+#endif
 	    if (NIL_P(tmp) || (level >= 0 && RARRAY_LEN(stack) / 2 >= level)) {
 		rb_ary_push(result, elt);
 	    }
@@ -3369,6 +3400,7 @@
 		*modified = 1;
 		id = (st_data_t)tmp;
 		if (st_lookup(memo, id, 0)) {
+		    st_free_table(memo);
 		    rb_raise(rb_eArgError, "tried to flatten recursive array");
 		}
 		st_insert(memo, id, (st_data_t)Qtrue);
@@ -3388,6 +3420,11 @@
 	ary = rb_ary_pop(stack);
     }
 
+    st_free_table(memo);
+
+#if !WITH_OBJC
+    RBASIC(result)->klass = rb_class_of(ary);
+#endif
     return result;
 }
 
@@ -3648,8 +3685,8 @@
     VALUE num;
     long r, n, i;
 
+    n = RARRAY_LEN(ary);                  /* Array length */
     RETURN_ENUMERATOR(ary, argc, argv);   /* Return enumerator if no block */
-    n = RARRAY_LEN(ary);                  /* Array length */
     rb_scan_args(argc, argv, "01", &num);
     r = NIL_P(num) ? n : NUM2LONG(num);   /* Permutation size from argument */
 
@@ -3735,7 +3772,6 @@
 {
     long n, i, len;
 
-    RETURN_ENUMERATOR(ary, 1, &num);
     n = NUM2LONG(num);
     RETURN_ENUMERATOR(ary, 1, &num);
     len = RARRAY_LEN(ary);
@@ -4017,6 +4053,15 @@
 }
 
 static void
+imp_rb_array_replaceObjectsInRangeWithObjectsCount(void *rcv, SEL sel,
+    CFRange range, const void **objects, CFIndex count)
+{
+    PREPARE_RCV(rcv);
+    CFArrayReplaceValues((CFMutableArrayRef)rcv, range, objects, count);
+    RESTORE_RCV(rcv);
+}
+
+static void
 imp_rb_array_addObject(void *rcv, SEL sel, void *obj)
 {
     PREPARE_RCV(rcv);
@@ -4054,6 +4099,8 @@
     INSTALL_METHOD("removeObjectAtIndex:", imp_rb_array_removeObjectAtIndex);
     INSTALL_METHOD("replaceObjectAtIndex:withObject:", 
 	imp_rb_array_replaceObjectAtIndexWithObject);
+    INSTALL_METHOD("replaceObjectsInRange:withObjects:count:",
+	imp_rb_array_replaceObjectsInRangeWithObjectsCount);
     INSTALL_METHOD("addObject:", imp_rb_array_addObject);
 
     /* This is to work around a bug where CF will try to call an non-existing 
@@ -4071,18 +4118,6 @@
 #undef INSTALL_METHOD
 }
 
-void
-rb_ary_set_named_args(VALUE ary, bool flag)
-{
-    rb_objc_ary_get_struct2(ary)->named_args = flag;
-}
-
-bool
-rb_ary_is_named_args(VALUE ary)
-{
-    struct rb_objc_ary_struct *s = rb_objc_ary_get_struct(ary);
-    return s != NULL && s->named_args;
-}
 #endif
 
 /* Arrays are ordered, integer-indexed collections of any object. 
@@ -4188,7 +4223,7 @@
     rb_define_method(rb_cArray, "compact!", rb_ary_compact_bang, 0);
     rb_define_method(rb_cArray, "flatten", rb_ary_flatten, -1);
     rb_define_method(rb_cArray, "flatten!", rb_ary_flatten_bang, -1);
-    rb_define_method(rb_cArray, "nitems", rb_ary_nitems, 0);
+    rb_define_method(rb_cArray, "_count", rb_ary_count, -1);
     rb_define_method(rb_cArray, "shuffle!", rb_ary_shuffle_bang, 0);
     rb_define_method(rb_cArray, "shuffle", rb_ary_shuffle, 0);
     rb_define_method(rb_cArray, "choice", rb_ary_choice, 0);

Modified: MacRuby/branches/testing/benchmark/bmx_temp.rb
===================================================================
--- MacRuby/branches/testing/benchmark/bmx_temp.rb	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/benchmark/bmx_temp.rb	2008-06-05 08:33:02 UTC (rev 249)
@@ -0,0 +1,9 @@
+def m
+  nil
+end
+
+i=0
+while i<800000 # benchmark loop 2
+  i+=1
+  m; m; m; m; m; m; m; m;
+end

Modified: MacRuby/branches/testing/bin/gem
===================================================================
--- MacRuby/branches/testing/bin/gem	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/bin/gem	2008-06-05 08:33:02 UTC (rev 249)
@@ -7,11 +7,12 @@
 
 require 'rubygems'
 require 'rubygems/gem_runner'
+require 'rubygems/exceptions'
 
-required_version = Gem::Requirement.new ">= 1.8.3"
+required_version = Gem::Requirement.new "> 1.8.3"
 
-unless required_version.satisfied_by? Gem::Version.new(RUBY_VERSION) then
-  abort "Expected Ruby Version #{required_version}, was #{RUBY_VERSION}"
+unless required_version.satisfied_by? Gem.ruby_version then
+  abort "Expected Ruby Version #{required_version}, was #{Gem.ruby_version}"
 end
 
 # We need to preserve the original ARGV to use for passing gem options
@@ -19,5 +20,9 @@
 # it...its for the source building process.
 args = !ARGV.include?("--") ? ARGV.clone : ARGV[0...ARGV.index("--")]
 
-Gem::GemRunner.new.run args
+begin
+  Gem::GemRunner.new.run args
+rescue Gem::SystemExitException => e
+  exit e.exit_code
+end
 

Modified: MacRuby/branches/testing/blockinlining.c
===================================================================
--- MacRuby/branches/testing/blockinlining.c	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/blockinlining.c	2008-06-05 08:33:02 UTC (rev 249)
@@ -2,13 +2,16 @@
 
   blockinlining.c -
 
-  $Author: akr $
+  $Author: ko1 $
 
   Copyright (C) 2004-2007 Koichi Sasada
 
 **********************************************************************/
 
 #include "ruby/ruby.h"
+#if WITH_OBJC
+# define process_named_args(x) (x)
+#endif
 #include "ruby/node.h"
 #include "vm_core.h"
 
@@ -195,7 +198,7 @@
 	    th->cfp->lfp[0] = GC_GUARDED_PTR(&block);
 	    argv[0] = INT2FIX(0);
 	    argv[1] = num;
-	    val = vm_yield(th, 2, argv);
+	    val = rb_yield_values(2, argv);
 	    if (val == Qundef) {
 		return num;
 	    }
@@ -314,7 +317,7 @@
 	    th->cfp->lfp[0] = GC_GUARDED_PTR(&block);
 	    argv[0] = beg;
 	    argv[1] = end;
-	    val = vm_yield(th, 2, argv);
+	    val = rb_yield_values(2, argv);
 	    if (val == Qundef) {
 		return range;
 	    }
@@ -444,7 +447,7 @@
 	    th->cfp->lfp[0] = GC_GUARDED_PTR(&block);
 	    argv[0] = 0;
 	    argv[1] = ary;
-	    val = vm_yield(th, 2, argv);
+	    val = rb_yield_values(2, argv);
 	    if (val == Qundef) {
 		return ary;
 	    }

Modified: MacRuby/branches/testing/bootstraptest/test_eval.rb
===================================================================
--- MacRuby/branches/testing/bootstraptest/test_eval.rb	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/bootstraptest/test_eval.rb	2008-06-05 08:33:02 UTC (rev 249)
@@ -208,3 +208,77 @@
   end
   Foo.add_method
 }, '[ruby-core:14556] reported by Frederick Cheung'
+
+assert_equal 'ok', %q{
+  class Module
+    def my_module_eval(&block)
+      module_eval(&block)
+    end
+  end
+  class String
+    Integer.my_module_eval do
+      def hoge; end
+    end
+  end
+  if Integer.instance_methods(false).map{|m|m.to_sym}.include?(:hoge) &&
+     !String.instance_methods(false).map{|m|m.to_sym}.include?(:hoge)
+    :ok
+  else
+    :ng
+  end
+}, "[ruby-dev:34236]"
+
+assert_equal 'ok', %q{
+  begin
+    eval("class nil::Foo; end")
+    :ng
+  rescue Exception
+    :ok
+  end
+}
+
+assert_equal 'ok', %q{
+  begin
+    0.instance_eval { def m() :m end }
+    1.m
+    :ng
+  rescue Exception
+    :ok
+  end
+}, '[ruby-dev:34579]'
+
+assert_equal 'ok', %q{
+  begin
+    12.instance_eval { @@a }
+  rescue NameError
+    :ok
+  end
+}, '[ruby-core:16794]'
+
+assert_equal 'ok', %q{
+  begin
+    12.instance_exec { @@a }
+  rescue NameError
+    :ok
+  end
+}, '[ruby-core:16794]'
+
+assert_equal 'ok', %q{
+  begin
+    nil.instance_eval {
+      def a() :a end
+    }
+  rescue TypeError
+    :ok
+  end
+}, '[ruby-core:16796]'
+
+assert_equal 'ok', %q{
+  begin
+    nil.instance_exec {
+      def a() :a end
+    }
+  rescue TypeError
+    :ok
+  end
+}, '[ruby-core:16796]'

Modified: MacRuby/branches/testing/bootstraptest/test_jump.rb
===================================================================
--- MacRuby/branches/testing/bootstraptest/test_jump.rb	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/bootstraptest/test_jump.rb	2008-06-05 08:33:02 UTC (rev 249)
@@ -248,3 +248,14 @@
     end
   end
 }, "[ruby-dev:31698]"
+
+assert_normal_exit %q{
+  f = 0
+  1.times do
+    begin
+      f += 1
+    ensure
+      redo unless f > 2
+    end
+  end
+}

Modified: MacRuby/branches/testing/bootstraptest/test_knownbug.rb
===================================================================
--- MacRuby/branches/testing/bootstraptest/test_knownbug.rb	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/bootstraptest/test_knownbug.rb	2008-06-05 08:33:02 UTC (rev 249)
@@ -7,9 +7,9 @@
   class C
     define_method(:foo) {
       if block_given?
-        :ok
-      else
         :ng
+      else
+        :ok
       end
     }
   end
@@ -30,28 +30,6 @@
 }, '[ruby-core:14813]'
 
 assert_equal 'ok', %q{
-  class X < RuntimeError;end
-  x = [X]
-  begin
-   raise X
-  rescue *x
-   :ok
-  end
-}, '[ruby-core:14537]'
-
-assert_normal_exit %q{
-  "abc".gsub(/./, "a" => "z")
-}
-
-assert_normal_exit %q{
-  Encoding.compatible?("",0)
-}
-
-assert_normal_exit %q{
-  "".center(1, "\x80".force_encoding("utf-8"))
-}, '[ruby-dev:33807]'
-
-assert_equal 'ok', %q{
   a = lambda {|x, y, &b| b }
   b = a.curry[1]
   if b.call(2){} == nil
@@ -62,10 +40,6 @@
 }, '[ruby-core:15551]'
 
 assert_normal_exit %q{
-  sprintf("% 0e", 1.0/0.0)
-}
-
-assert_normal_exit %q{
   g = Module.enum_for(:new)
   loop { g.next }
 }, '[ruby-dev:34128]'
@@ -111,134 +85,23 @@
 }, "[ ruby-Bugs-19304 ]"
 
 assert_equal 'ok', %q{
-  def a() end
-  begin
-    if defined?(a(1).a)
-      :ng
-    else
-      :ok
-    end
-  rescue
+  lambda {
+    break :ok
     :ng
-  end
-}, '[ruby-core:16010]'
+  }.call
+}, '[ruby-dev:34646]'
 
-assert_equal 'ok', %q{
-  def a() end
-  begin
-    if defined?(a::B)
-      :ng
-    else
-      :ok
-    end
-  rescue
-    :ng
-  end
-}, '[ruby-core:16010]'
-
-
-assert_equal 'ok', %q{
-  class Module
-    def my_module_eval(&block)
-      module_eval(&block)
-    end
-  end
-  class String
-    Integer.my_module_eval do
-      def hoge; end
-    end
-  end
-  if Integer.instance_methods(false).map{|m|m.to_sym}.include?(:hoge) &&
-     !String.instance_methods(false).map{|m|m.to_sym}.include?(:hoge)
-    :ok
-  else
-    :ng
-  end
-}, "[ruby-dev:34236]"
-
-assert_equal 'ok', %q{
-  def m
-    t = Thread.new { while true do // =~ "" end }
-    sleep 0.1
-    10.times {
-      if /((ab)*(ab)*)*(b)/ =~ "ab"*7
-        return :ng if !$4
-        return :ng if $~.size != 5
-      end
-    }
-    :ok
-  ensure
-    Thread.kill t
-  end
-  m
-}, '[ruby-dev:34492]'
-
 assert_normal_exit %q{
-  begin
-    r = 0**-1
-    r + r
-  rescue
-  end
-}, '[ruby-dev:34524]'
-
-assert_normal_exit %q{
-  begin
-    r = Marshal.load("\x04\bU:\rRational[\ai\x06i\x05")
-    r + r
-  rescue
-  end
-}, '[ruby-dev:34536]'
-
-assert_normal_exit %q{
-  begin
-    Struct.new(0)
-  rescue
-  end
+  eval("", method(:proc).call {}.binding)
 }
 
 assert_normal_exit %q{
-  defined? C && 0
+  a = []
+  100.times {|i| a << i << nil << nil }
+  p a.compact!
 }
 
-assert_normal_exit %q{
-  class C
-    def m
-      defined?(super())
-    end
-  end
-  C.new.m
-}
-
-assert_normal_exit %q{
-  [1,2,3].slice!(1,10000).inspect
-}
-
 assert_equal 'ok', %q{
-  begin
-    eval("class nil::Foo; end")
-    :ng
-  rescue Exception
-    :ok
-  end
-}
-
-assert_normal_exit %q{
-  at_exit { Fiber.new{}.resume }
-}
-
-assert_equal 'ok', %q{
-  lambda {
-    break :ok
-    :ng
-  }.call
-}, '[ruby-dev:34646]'
-
-assert_equal 'ok', %q{
-  begin
-    0.instance_eval { def m() :m end }
-    1.m
-    :ng
-  rescue Exception
-    :ok
-  end
-}, '[ruby-dev:34579]'
+  a = [false]
+  (a[0] &&= true) == false ? :ok : :ng
+}, '[ruby-dev:34679]'

Modified: MacRuby/branches/testing/bootstraptest/test_literal.rb
===================================================================
--- MacRuby/branches/testing/bootstraptest/test_literal.rb	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/bootstraptest/test_literal.rb	2008-06-05 08:33:02 UTC (rev 249)
@@ -176,3 +176,19 @@
   ObjectSpace.each_object(Module) {|m| m.name.inspect }
   :ok
 }
+
+assert_normal_exit %q{
+  begin
+    r = 0**-1
+    r + r
+  rescue
+  end
+}, '[ruby-dev:34524]'
+
+assert_normal_exit %q{
+  begin
+    r = Marshal.load("\x04\bU:\rRational[\ai\x06i\x05")
+    r + r
+  rescue
+  end
+}, '[ruby-dev:34536]'

Modified: MacRuby/branches/testing/bootstraptest/test_syntax.rb
===================================================================
--- MacRuby/branches/testing/bootstraptest/test_syntax.rb	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/bootstraptest/test_syntax.rb	2008-06-05 08:33:02 UTC (rev 249)
@@ -767,3 +767,53 @@
 }
 
 assert_valid_syntax('1.times {|i|print (42),1;}', '[ruby-list:44479]')
+
+assert_equal 'ok', %q{
+  def a() end
+  begin
+    if defined?(a(1).a)
+      :ng
+    else
+      :ok
+    end
+  rescue
+    :ng
+  end
+}, '[ruby-core:16010]'
+
+assert_equal 'ok', %q{
+  def a() end
+  begin
+    if defined?(a::B)
+      :ng
+    else
+      :ok
+    end
+  rescue
+    :ng
+  end
+}, '[ruby-core:16010]'
+
+assert_normal_exit %q{
+  defined? C && 0
+}
+
+assert_normal_exit %q{
+  class C
+    def m
+      defined?(super())
+    end
+  end
+  C.new.m
+}
+
+assert_equal 'ok', %q{
+  class X < RuntimeError;end
+  x = [X]
+  begin
+   raise X
+  rescue *x
+   :ok
+  end
+}, '[ruby-core:14537]'
+

Modified: MacRuby/branches/testing/bootstraptest/test_thread.rb
===================================================================
--- MacRuby/branches/testing/bootstraptest/test_thread.rb	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/bootstraptest/test_thread.rb	2008-06-05 08:33:02 UTC (rev 249)
@@ -246,3 +246,25 @@
     t.join
   }
 }
+
+assert_equal 'ok', %q{
+  def m
+    t = Thread.new { while true do // =~ "" end }
+    sleep 0.1
+    10.times {
+      if /((ab)*(ab)*)*(b)/ =~ "ab"*7
+        return :ng if !$4
+        return :ng if $~.size != 5
+      end
+    }
+    :ok
+  ensure
+    Thread.kill t
+  end
+  m
+}, '[ruby-dev:34492]'
+
+assert_normal_exit %q{
+  at_exit { Fiber.new{}.resume }
+}
+

Modified: MacRuby/branches/testing/bs.c
===================================================================
--- MacRuby/branches/testing/bs.c	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/bs.c	2008-06-05 08:33:02 UTC (rev 249)
@@ -26,7 +26,6 @@
  *  POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include "bs_lex.h"
 #include "bs.h"
 
 #include <libxml/xmlreader.h>
@@ -34,6 +33,8 @@
 #include <libgen.h>
 #include <unistd.h>
 
+#include "bs_lex.h"
+
 #define ASSERT_ALLOC(ptr) (assert(ptr != NULL))
 
 static inline char *
@@ -369,7 +370,7 @@
   unsigned int i;
 #define MAX_ARGS 128
   bs_element_arg_t args[MAX_ARGS];
-  char *protocol_name;
+  char *protocol_name = NULL;
   int func_ptr_arg_depth;
   bs_element_function_pointer_t *func_ptr;
   bool success;
@@ -436,10 +437,10 @@
     const char *name;
     unsigned int namelen;
     int node_type = -1;
-    bool eof;
+    bool eof = false;
     struct bs_xml_atom *atom;
     void *bs_element;
-    bs_element_type_t bs_element_type;
+    bs_element_type_t bs_element_type = 0;
 
     do {
       int retval = xmlTextReaderRead(reader);
@@ -1096,7 +1097,21 @@
     free(protocol_name);
 
   xmlFreeTextReader(reader);
-  
+
+  if (success && options == BS_PARSE_OPTIONS_LOAD_DYLIBS) {
+    char *p, buf[PATH_MAX];
+    strncpy(buf, path, sizeof buf);
+    p = strrchr(buf, '.');
+    assert(p != NULL);
+    strlcpy(p, ".dylib", p - path - 1);
+    if (access(buf, R_OK) == 0) {
+      if (dlopen(buf, RTLD_LAZY) == NULL) {
+        *error = dlerror();
+        success = false;
+      }
+    }
+  }
+
   return success;
 }
 

Modified: MacRuby/branches/testing/bs.h
===================================================================
--- MacRuby/branches/testing/bs.h	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/bs.h	2008-06-05 08:33:02 UTC (rev 249)
@@ -202,7 +202,10 @@
   (const char *path, bs_element_type_t type, void *value, void *context);
 
 typedef enum {
-  BS_PARSE_DEFAULT = 0
+  /* Default option: parse bridge support files. */
+  BS_PARSE_OPTIONS_DEFAULT = 0,
+  /* Parse bridge support files and dlopen(3) the dylib files, if any. */
+  BS_PARSE_OPTIONS_LOAD_DYLIBS
 } bs_parse_options_t;
 
 /* bs_parse() 
@@ -213,7 +216,7 @@
  * Returns true on success, otherwise false.
  *
  * path: the full path of the bridge support file to parse.
- * options: parsing options, reserved for future use. You can pass 0 for now.
+ * options: parsing options.
  * callback: a callback function pointer.
  * context: a contextual data pointer that will be passed to the callback 
  * function.

Modified: MacRuby/branches/testing/class.c
===================================================================
--- MacRuby/branches/testing/class.c	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/class.c	2008-06-05 08:33:02 UTC (rev 249)
@@ -134,7 +134,6 @@
 {
     VALUE obj;
     Class ocklass, ocsuper;
-    size_t size;
     char ocname[128];
 
     if (name == NULL) {
@@ -146,7 +145,7 @@
 	    long count = 1;
 	    snprintf(ocname, sizeof ocname, "RB%s", name);
 	    while (objc_getClass(ocname) != NULL)
-		snprintf(ocname, sizeof ocname, "RB%s%d", name, ++count);
+		snprintf(ocname, sizeof ocname, "RB%s%ld", name, ++count);
 	    rb_warning("can't create `%s' as an Objective-C class, because " \
 		       "it already exists, instead using `%s'", name, ocname);
 	}
@@ -168,7 +167,7 @@
     RBASIC(obj)->isa = ocklass->isa;
     RCLASS(obj)->ocklass = ocklass;
 
-    rb_objc_retain(obj); /* classes should never be released */
+    rb_objc_retain((const void *)obj); /* classes should never be released */
 
     if (name == NULL)
 	FL_SET(obj, RCLASS_ANONYMOUS);
@@ -454,7 +453,7 @@
 	    NEWOBJ(obj2, struct RClass); 
 	    OBJSETUP(obj2, rb_cClass, T_CLASS); 
 	    klass = (VALUE)obj2; 
-	    rb_objc_retain(klass); 
+	    rb_objc_retain((const void *)klass); 
 	    class_init(klass); 
 	    OBJ_INFECT(klass, super); 
 	    RCLASS_SUPER(klass) = super; 

Modified: MacRuby/branches/testing/common.mk
===================================================================
--- MacRuby/branches/testing/common.mk	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/common.mk	2008-06-05 08:33:02 UTC (rev 249)
@@ -110,9 +110,11 @@
 
 BOOTSTRAPRUBY = $(BASERUBY)
 
+COMPILE_PRELUDE = $(MINIRUBY) -I$(srcdir) -rrbconfig $(srcdir)/tool/compile_prelude.rb
+
 VCS           = svn
 
-all: $(MKFILES) $(PREP) incs $(RBCONFIG) $(LIBRUBY) encs
+all: $(MKFILES) incs $(PREP) $(RBCONFIG) $(LIBRUBY) encs
 	@$(MINIRUBY) $(srcdir)/ext/extmk.rb --make="$(MAKE)" $(EXTMK_ARGS)
 prog: $(PROGRAM) $(WPROGRAM)
 
@@ -373,12 +375,12 @@
 		-install_name=$(RUBY_INSTALL_NAME) \
 		-so_name=$(RUBY_SO_NAME) rbconfig.rb
 
-encs: enc.mk
+encs: enc.mk $(LIBRUBY)
 	$(MINIRUBY) -run -e mkdir -- -p "$(EXTOUT)/$(arch)/enc/trans" enc/trans
 	$(MAKE) -f enc.mk $(MFLAGS)
 
 enc.mk: $(srcdir)/enc/make_encmake.rb $(srcdir)/enc/Makefile.in $(srcdir)/enc/depend \
-	$(srcdir)/lib/mkmf.rb $(RBCONFIG)
+	$(srcdir)/lib/mkmf.rb $(PREP)
 	$(MINIRUBY) $(srcdir)/enc/make_encmake.rb --builtin-encs="$(BUILTIN_ENCOBJS)" $@
 
 .PRECIOUS: $(MKFILES)
@@ -471,7 +473,7 @@
   {$(VPATH)}util.h {$(VPATH)}signal.h {$(VPATH)}vm_core.h \
   {$(VPATH)}debug.h {$(VPATH)}vm_opts.h {$(VPATH)}id.h \
   {$(VPATH)}thread_$(THREAD_MODEL).h {$(VPATH)}dln.h \
-  {$(VPATH)}eval_error.c {$(VPATH)}eval_method.c {$(VPATH)}eval_safe.c \
+  {$(VPATH)}eval_error.c {$(VPATH)}eval_safe.c \
   {$(VPATH)}eval_jump.c
 load.$(OBJEXT): {$(VPATH)}load.c {$(VPATH)}eval_intern.h \
   {$(VPATH)}ruby.h {$(VPATH)}config.h {$(VPATH)}defines.h \
@@ -616,7 +618,7 @@
   {$(VPATH)}eval_intern.h {$(VPATH)}util.h {$(VPATH)}dln.h
 time.$(OBJEXT): {$(VPATH)}time.c {$(VPATH)}ruby.h {$(VPATH)}config.h \
   {$(VPATH)}defines.h {$(VPATH)}missing.h {$(VPATH)}intern.h \
-  {$(VPATH)}st.h
+  {$(VPATH)}st.h {$(VPATH)}encoding.h 
 util.$(OBJEXT): {$(VPATH)}util.c {$(VPATH)}ruby.h {$(VPATH)}config.h \
   {$(VPATH)}defines.h {$(VPATH)}missing.h {$(VPATH)}intern.h \
   {$(VPATH)}st.h {$(VPATH)}util.h
@@ -648,7 +650,8 @@
   {$(VPATH)}vm_core.h {$(VPATH)}debug.h {$(VPATH)}vm_opts.h {$(VPATH)}id.h \
   {$(VPATH)}thread_$(THREAD_MODEL).h {$(VPATH)}dln.h {$(VPATH)}vm.h \
   {$(VPATH)}vm_insnhelper.c {$(VPATH)}insns.inc {$(VPATH)}vm_evalbody.c \
-  {$(VPATH)}vmtc.inc {$(VPATH)}vm.inc {$(VPATH)}insns.def
+  {$(VPATH)}vmtc.inc {$(VPATH)}vm.inc {$(VPATH)}insns.def \
+  {$(VPATH)}vm_method.c {$(VPATH)}vm_eval.c
 vm_dump.$(OBJEXT): {$(VPATH)}vm_dump.c {$(VPATH)}ruby.h \
   {$(VPATH)}config.h {$(VPATH)}defines.h {$(VPATH)}missing.h \
   {$(VPATH)}intern.h {$(VPATH)}st.h {$(VPATH)}node.h {$(VPATH)}vm_core.h \
@@ -746,14 +749,11 @@
 miniprelude.c: $(srcdir)/tool/compile_prelude.rb $(srcdir)/prelude.rb
 	$(BASERUBY) -I$(srcdir) $(srcdir)/tool/compile_prelude.rb $(srcdir)/prelude.rb $@
 
-prelude.c: $(srcdir)/tool/compile_prelude.rb $(PRELUDE_SCRIPTS) $(RBCONFIG) $(PREP)
-	$(MINIRUBY) -I$(srcdir) -rrbconfig $(srcdir)/tool/compile_prelude.rb \
-		$(PRELUDE_SCRIPTS) $@.new
-	$(IFCHANGE) "$@" "$@.new"
+prelude.c: $(srcdir)/tool/compile_prelude.rb $(PRELUDE_SCRIPTS) $(PREP)
+	$(COMPILE_PRELUDE) $(PRELUDE_SCRIPTS) $@
 
 golf_prelude.c: $(srcdir)/tool/compile_prelude.rb $(srcdir)/prelude.rb $(srcdir)/golf_prelude.rb $(PREP)
-	$(MINIRUBY) -I$(srcdir) -rrbconfig $(srcdir)/tool/compile_prelude.rb $(srcdir)/golf_prelude.rb $@.new
-	$(IFCHANGE) "$@" "$@.new"
+	$(COMPILE_PRELUDE) $(srcdir)/golf_prelude.rb $@
 
 prereq: incs srcs preludes
 

Modified: MacRuby/branches/testing/compile.c
===================================================================
--- MacRuby/branches/testing/compile.c	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/compile.c	2008-06-05 08:33:02 UTC (rev 249)
@@ -2,7 +2,7 @@
 
   compile.c - ruby node tree -> VM instruction sequence
 
-  $Author: ko1 $
+  $Author: nobu $
   created at: 04/01/01 03:42:15 JST
 
   Copyright (C) 2004-2007 Koichi Sasada
@@ -26,12 +26,8 @@
 #define va_init_list(a,b) va_start(a)
 #endif
 
-/* iseq.c */
 VALUE iseq_load(VALUE self, VALUE data, VALUE parent, VALUE opt);
 
-/* vm.c */
-VALUE vm_eval(void *);
-
 /* types */
 
 typedef struct iseq_link_element {
@@ -138,7 +134,7 @@
  */
 
 static void
-verify_list(ISEQ_ARG_DECLARE char *info, LINK_ANCHOR *anchor)
+verify_list(ISEQ_ARG_DECLARE const char *info, LINK_ANCHOR *anchor)
 {
 #if CPDEBUG
     int flag = 0;
@@ -277,6 +273,7 @@
 	    COMPILE_POPED(ret, "ensure", node);
 	    break;
 	  case ISEQ_TYPE_DEFINED_GUARD:
+	    iseq_set_local_table(iseq, 0);
 	    COMPILE(ret, "defined guard", node);
 	    break;
 	  default:
@@ -285,7 +282,7 @@
     }
 
     if (iseq->type == ISEQ_TYPE_RESCUE || iseq->type == ISEQ_TYPE_ENSURE) {
-	ADD_INSN2(ret, 0, getdynamic, INT2FIX(1), INT2FIX(0));
+	ADD_INSN2(ret, 0, getdynamic, INT2FIX(2), INT2FIX(0));
 	ADD_INSN1(ret, 0, throw, INT2FIX(0) /* continue throw */ );
     }
     else {
@@ -299,12 +296,11 @@
 iseq_translate_threaded_code(rb_iseq_t *iseq)
 {
 #if OPT_DIRECT_THREADED_CODE || OPT_CALL_THREADED_CODE
-
+    extern const void **vm_get_insns_address_table(void);
 #if OPT_DIRECT_THREADED_CODE
-    const void *const *table = (const void **)vm_eval(0);
+    const void * const *table = vm_get_insns_address_table();
 #else
-    extern const void *const *get_insns_address_table();
-    const void *const *table = get_insns_address_table();
+    const void * const *table = vm_get_insns_address_table();
 #endif
     int i;
 
@@ -776,7 +772,8 @@
 	id_dollar_bang = rb_intern("#$!");
     }
     iseq->local_table = (ID *)ALLOC_N(ID *, 1);
-    iseq->local_table_size = iseq->local_size = 1;
+    iseq->local_table_size = 1;
+    iseq->local_size = iseq->local_table_size + 1;
     iseq->local_table[0] = id_dollar_bang;
     return COMPILE_OK;
 }
@@ -1002,13 +999,15 @@
     }
 
     iseq->local_size = iseq->local_table_size = size;
+    iseq->local_size += 1;
+    /*
+      if (lfp == dfp ) { // top, class, method
+	  dfp[-1]: svar
+      else {             // block
+          dfp[-1]: cref
+      }
+     */
 
-    if (iseq->type == ISEQ_TYPE_METHOD ||
-	iseq->type == ISEQ_TYPE_CLASS  ||
-	iseq->type == ISEQ_TYPE_TOP) {
-	iseq->local_size += 1 /* svar */;
-    }
-
     debugs("iseq_set_local_table: %d, %d\n", iseq->local_size, iseq->local_table_size);
     return COMPILE_OK;
 }
@@ -1368,7 +1367,7 @@
 
     list = lobj->link.next;
     while (list) {
-	if (list->type == ISEQ_ELEMENT_INSN) {
+	if (list->type == ISEQ_ELEMENT_INSN || list->type == ISEQ_ELEMENT_ADJUST) {
 	    break;
 	}
 	list = list->next;
@@ -1382,7 +1381,7 @@
     LINK_ELEMENT *list = iobj->link.next;
 
     while (list) {
-	if (list->type == ISEQ_ELEMENT_INSN) {
+	if (list->type == ISEQ_ELEMENT_INSN || list->type == ISEQ_ELEMENT_ADJUST) {
 	    return list;
 	}
 	list = list->next;
@@ -1396,7 +1395,7 @@
     LINK_ELEMENT *list = iobj->link.prev;
 
     while (list) {
-	if (list->type == ISEQ_ELEMENT_INSN) {
+	if (list->type == ISEQ_ELEMENT_INSN || list->type == ISEQ_ELEMENT_ADJUST) {
 	    return list;
 	}
 	list = list->prev;
@@ -2026,20 +2025,11 @@
 	    }
 
 	    iseq_add_mark_object_compile_time(iseq, ary);
-#if WITH_OBJC
-	    if (node_root->flags & NODE_ARRAY_NAMED_ARGS)
-		rb_ary_set_named_args(ary, true);
-#endif
 	    ADD_INSN1(ret, nd_line(node_root), duparray, ary);
 	}
     }
     else {
 	if (!poped) {
-#if WITH_OBJC
-	    if (node_root->flags & NODE_ARRAY_NAMED_ARGS)
-		ADD_INSN1(anchor, line, newarray_named_args, INT2FIX(len));
-	    else
-#endif
 	    ADD_INSN1(anchor, line, newarray, INT2FIX(len));
 	}
 	APPEND_LIST(ret, anchor);
@@ -2322,7 +2312,7 @@
 defined_expr(rb_iseq_t *iseq, LINK_ANCHOR *ret,
 	     NODE *node, LABEL **lfinish, VALUE needstr)
 {
-    char *estr = 0;
+    const char *estr = 0;
     enum node_type type;
 
     switch (type = nd_type(node)) {
@@ -2347,18 +2337,10 @@
 	do {
 	    defined_expr(iseq, ret, vals->nd_head, lfinish, Qfalse);
 
-	    if (lfinish[1]) {
-		ADD_INSNL(ret, nd_line(node), branchunless, lfinish[1]);
-	    }
-	    else {
-		LABEL *lcont = NEW_LABEL(nd_line(node));
+	    if (!lfinish[1]) {
 		lfinish[1] = NEW_LABEL(nd_line(node));
-		ADD_INSNL(ret, nd_line(node), branchif, lcont);
-		ADD_LABEL(ret, lfinish[1]);
-		ADD_INSN(ret, nd_line(node), putnil);
-		ADD_INSNL(ret, nd_line(node), jump, lfinish[0]);
-		ADD_LABEL(ret, lcont);
 	    }
+	    ADD_INSNL(ret, nd_line(node), branchunless, lfinish[1]);
 	} while ((vals = vals->nd_next) != NULL);
       }
       case NODE_STR:
@@ -2950,12 +2932,24 @@
 	LABEL *break_label = iseq->compile_data->end_label = NEW_LABEL(nd_line(node));	/* break */
 	LABEL *end_label = NEW_LABEL(nd_line(node));
 
+	LABEL *next_catch_label = NEW_LABEL(nd_line(node));
+	LABEL *tmp_label = NULL;
+
 	iseq->compile_data->loopval_popped = 0;
 	iseq->compile_data->ensure_node_stack = 0;
 
 	if (type == NODE_OPT_N || node->nd_state == 1) {
 	    ADD_INSNL(ret, nd_line(node), jump, next_label);
 	}
+	else {
+	    tmp_label = NEW_LABEL(nd_line(node));
+	    ADD_INSNL(ret, nd_line(node), jump, tmp_label);
+	}
+	ADD_INSN(ret, nd_line(node), putnil);
+	ADD_LABEL(ret, next_catch_label);
+	ADD_INSN(ret, nd_line(node), pop);
+	ADD_INSNL(ret, nd_line(node), jump, next_label);
+	if (tmp_label) ADD_LABEL(ret, tmp_label);
 
 	ADD_LABEL(ret, redo_label);
 	COMPILE_POPED(ret, "while body", node->nd_body);
@@ -2987,7 +2981,7 @@
 	    ADD_INSN(ret, nd_line(node), putnil);
 	}
 
-	ADD_LABEL(ret, break_label);	/* braek */
+	ADD_LABEL(ret, break_label);	/* break */
 
 	if (poped) {
 	    ADD_INSN(ret, nd_line(node), pop);
@@ -2995,8 +2989,8 @@
 
 	ADD_CATCH_ENTRY(CATCH_TYPE_BREAK, redo_label, break_label,
 			0, break_label);
-	ADD_CATCH_ENTRY(CATCH_TYPE_NEXT | 0x10000, redo_label,
-			break_label, 0, iseq->compile_data->start_label);
+	ADD_CATCH_ENTRY(CATCH_TYPE_NEXT, redo_label, break_label, 0,
+			next_catch_label);
 	ADD_CATCH_ENTRY(CATCH_TYPE_REDO, redo_label, break_label, 0,
 			iseq->compile_data->redo_label);
 
@@ -3134,13 +3128,12 @@
 	    rb_iseq_t *ip;
 	    ip = iseq;
 	    while (ip) {
-		level = 0x8000;
+		level = 0x8000 | 0x4000;
 		if (ip->compile_data->redo_label != 0) {
 		    /* while loop */
 		    break;
 		}
 		else if (ip->type == ISEQ_TYPE_BLOCK) {
-		    level |= 0x4000;
 		    break;
 		}
 		else if (ip->type == ISEQ_TYPE_EVAL) {
@@ -3282,8 +3275,7 @@
 		  case NODE_ARRAY:
 		    while (narg) {
 			COMPILE(ret, "rescue arg", narg->nd_head);
-			ADD_INSN2(ret, nd_line(node), getdynamic, INT2FIX(1),
-				  INT2FIX(0));
+			ADD_INSN2(ret, nd_line(node), getdynamic, INT2FIX(2), INT2FIX(0));
 			ADD_SEND(ret, nd_line(node), ID2SYM(idEqq), INT2FIX(1));
 			ADD_INSNL(ret, nd_line(node), branchif, label_hit);
 			narg = narg->nd_next;
@@ -3292,8 +3284,7 @@
 		  case NODE_SPLAT:
 		  case NODE_ARGSCAT:
 		  case NODE_ARGSPUSH:
-		    ADD_INSN2(ret, nd_line(node), getdynamic, INT2FIX(1),
-			      INT2FIX(0));
+		    ADD_INSN2(ret, nd_line(node), getdynamic, INT2FIX(2), INT2FIX(0));
 		    COMPILE(ret, "rescue/cond splat", narg);
 		    ADD_INSN1(ret, nd_line(node), checkincludearray, Qtrue);
 		    ADD_INSN(ret, nd_line(node), swap);
@@ -3308,8 +3299,7 @@
 	    else {
 		ADD_INSN1(ret, nd_line(node), putobject,
 			  rb_eStandardError);
-		ADD_INSN2(ret, nd_line(node), getdynamic, INT2FIX(1),
-			  INT2FIX(0));
+		ADD_INSN2(ret, nd_line(node), getdynamic, INT2FIX(2), INT2FIX(0));
 		ADD_SEND(ret, nd_line(node), ID2SYM(idEqq), INT2FIX(1));
 		ADD_INSNL(ret, nd_line(node), branchif, label_hit);
 	    }
@@ -4030,8 +4020,7 @@
 	    if (idx < 0) {
 		rb_bug("unknown dvar (%s)", rb_id2name(node->nd_vid));
 	    }
-	    ADD_INSN2(ret, nd_line(node), getdynamic, INT2FIX(ls - idx),
-		      INT2FIX(lv));
+	    ADD_INSN2(ret, nd_line(node), getdynamic, INT2FIX(ls - idx), INT2FIX(lv));
 	}
 	break;
       }
@@ -4503,8 +4492,7 @@
       case NODE_ERRINFO:{
 	if (!poped) {
 	    if (iseq->type == ISEQ_TYPE_RESCUE) {
-		ADD_INSN2(ret, nd_line(node), getdynamic, INT2FIX(1),
-			  INT2FIX(0));
+		ADD_INSN2(ret, nd_line(node), getdynamic, INT2FIX(2), INT2FIX(0));
 	    }
 	    else {
 		rb_iseq_t *ip = iseq;
@@ -4517,8 +4505,7 @@
 		    level++;
 		}
 		if (ip) {
-		    ADD_INSN2(ret, nd_line(node), getdynamic, INT2FIX(1),
-			      INT2FIX(level));
+		    ADD_INSN2(ret, nd_line(node), getdynamic, INT2FIX(2), INT2FIX(level));
 		}
 		else {
 		    ADD_INSN(ret, nd_line(node), putnil);
@@ -4970,6 +4957,7 @@
 			{
 			    int i;
 			    op = rb_convert_type(op, T_ARRAY, "Array", "to_ary");
+			    op = rb_ary_dup(op);
 			    for (i=0; i<RARRAY_LEN(op); i+=2) {
 				VALUE sym = rb_ary_entry(op, i+1);
 				LABEL *label =

Modified: MacRuby/branches/testing/configure.in
===================================================================
--- MacRuby/branches/testing/configure.in	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/configure.in	2008-06-05 08:33:02 UTC (rev 249)
@@ -180,14 +180,17 @@
 
 dnl Checks for programs.
 
+: ${CFLAGS=} ${CXXFLAGS=}
 if test x"${build}" != x"${host}"; then
   AC_CHECK_TOOL(CC, gcc)
 fi
 AC_PROG_CC
 AC_PROG_CXX
 AC_PROG_GCC_TRADITIONAL
+test $ac_cv_prog_cc_g = yes && : ${debugflags=-g}
 if test "$GCC" = yes; then
     linker_flag=-Wl,
+    : ${optflags=-O2} ${warnflags="-Wall -Wno-parentheses"}
 else
     linker_flag=
 fi
@@ -1630,7 +1633,7 @@
 	;;
     darwin*)
 	LIBRUBY_SO='lib$(RUBY_SO_NAME).$(MAJOR).$(MINOR).$(TEENY).dylib'
-	LIBRUBY_LDSHARED='$(CC) -dynamiclib -undefined suppress -flat_namespace'
+	LIBRUBY_LDSHARED='cc -dynamiclib -undefined suppress -flat_namespace'
 	LIBRUBY_DLDFLAGS='-install_name $(libdir)/lib$(RUBY_SO_NAME).dylib -current_version $(MAJOR).$(MINOR).$(TEENY) -compatibility_version $(MAJOR).$(MINOR)'
 	LIBRUBY_ALIASES='lib$(RUBY_SO_NAME).$(MAJOR).$(MINOR).dylib lib$(RUBY_SO_NAME).dylib'
 	;;
@@ -1771,9 +1774,10 @@
 test -z "$CFLAGS" || CFLAGS="$CFLAGS "; CFLAGS="$CFLAGS"'${cflags}'
 test -z "$CPPFLAGS" || CPPFLAGS="$CPPFLAGS "; CPPFLAGS="$CPPFLAGS"'${cppflags}'
 AC_SUBST(cppflags, [])dnl
-AC_SUBST(cflags, ['${optflags} ${debugflags}'])dnl
+AC_SUBST(cflags, ['${optflags} ${debugflags} ${warnflags}'])dnl
 AC_SUBST(optflags)dnl
 AC_SUBST(debugflags)dnl
+AC_SUBST(warnflags)dnl
 AC_SUBST(XCFLAGS)dnl
 AC_SUBST(XLDFLAGS)dnl
 AC_SUBST(LIBRUBY_LDSHARED)
@@ -1819,15 +1823,7 @@
     rubyw_install_name="$RUBYW_INSTALL_NAME"
     ;;
 esac
-case "$target_os" in
-  cygwin*|mingw*|*djgpp*|os2-emx*)
-    RUBY_LIB_PREFIX="/lib/ruby"
-    ;;
-  *)
-    RUBY_LIB_PREFIX="${prefix}/lib/ruby"
-    ;;
-esac
-RUBY_LIB_PATH="${RUBY_LIB_PREFIX}/${MAJOR}.${MINOR}.${TEENY}"
+RUBY_LIB_PREFIX=`eval echo \\"${libdir}/ruby\\"`
 
 AC_ARG_WITH(sitedir,
 	    [  --with-sitedir=DIR      site libraries in DIR [PREFIX/lib/ruby/site_ruby]],

Modified: MacRuby/branches/testing/cont.c
===================================================================
--- MacRuby/branches/testing/cont.c	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/cont.c	2008-06-05 08:33:02 UTC (rev 249)
@@ -108,10 +108,10 @@
 static void
 cont_save_machine_stack(rb_thread_t *th, rb_context_t *cont)
 {
+#if !WITH_OBJC
     int size;
     rb_thread_t *sth = &cont->saved_thread;
 
-#if !WITH_OBJC
     SET_MACHINE_STACK_END(&th->machine_stack_end);
 #ifdef __ia64
     th->machine_register_stack_end = rb_ia64_bsp();

Modified: MacRuby/branches/testing/dir.c
===================================================================
--- MacRuby/branches/testing/dir.c	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/dir.c	2008-06-05 08:33:02 UTC (rev 249)
@@ -460,7 +460,7 @@
 
     Data_Get_Struct(dir, struct dir_data, dirp);
     if (dirp->path) {
-	char *c = rb_obj_classname(dir);
+	const char *c = rb_obj_classname(dir);
 	int len = strlen(c) + strlen(dirp->path) + 4;
 	VALUE s = rb_str_new(0, len);
 	snprintf(RSTRING_PTR(s), len+1, "#<%s:%s>", c, dirp->path);
@@ -715,7 +715,7 @@
 	    chdir_thread = Qnil;
 	dir_chdir(args->old_path);
     }
-    rb_objc_release(args->old_path);
+    rb_objc_release((const void *)args->old_path);
     return Qnil;
 }
 
@@ -786,7 +786,7 @@
 	char *cwd = my_getcwd();
 
 	args.old_path = rb_tainted_str_new2(cwd); xfree(cwd);
-	rb_objc_retain(args.old_path);
+	rb_objc_retain((const void *)args.old_path);
 	args.new_path = path;
 	args.done = Qfalse;
 	return rb_ensure(chdir_yield, (VALUE)&args, chdir_restore, (VALUE)&args);
@@ -1690,7 +1690,7 @@
 	ary = rb_push_glob(str, flags);
     }
     else {
-	VALUE v = ary;
+	volatile VALUE v = ary;
 	ary = dir_globs(RARRAY_LEN(v), RARRAY_PTR(v), flags);
     }
 

Modified: MacRuby/branches/testing/doc/NEWS
===================================================================
--- MacRuby/branches/testing/doc/NEWS	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/doc/NEWS	2008-06-05 08:33:02 UTC (rev 249)
@@ -7,6 +7,8 @@
           o Block arguments
           o New semantics for block arguments
           o Block local variables
+    * Array
+          o Array#nitems was removed (use count {|i| !i.nil?})
     * String
           o No longer an Enumerable
           o ?c semantics
@@ -33,7 +35,6 @@
           o SecurityError
           o Removed Exception#to_str [Ruby2]
     * Array
-          o Array#nitems
           o Array#[m,n] = nil places nil in the array.
     * Hash
           o Hash#to_s is equivalent to Hash#inspect
@@ -49,12 +50,9 @@
           o Dir.exist?
     * IO operations
           o Non-blocking IO
-          o IO#getbyte, IO#readbyte, StringIO#getbyte, StringIO#readbyte
           o Kernel#open takes encoding specified
           o IO#initialize now accepts an IO argument
           o StringIO#readpartial
-          o IO#lines
-          o IO#bytes
           o IO.try_convert
           o Limit input in IO#gets, IO#readline, IO#readlines, IO#each_line, IO#lines, IO.foreach, IO.readlines, StringIO#gets, StringIO#readline, StringIO#each, StringIO#readlines
           o IO#ungetc, StringIO#ungetc
@@ -89,9 +87,7 @@
           o Newlines allowed before ternary colon
     * Kernel and Object
           o BasicObject
-          o #instance_exec
           o Object#=~
-          o Object#tap
           o Kernel#instance_variable_defined?
           o Kernel#define_singleton_method
           o Kernel#singleton_methods, Kernel#methods
@@ -100,7 +96,6 @@
           o Module#class_variable_defined?
           o #class_variable_{set,get}
           o Class of singleton classes
-          o #module_exec
     * Binding#eval
     * Blocks and Procs
           o Arity of blocks without arguments
@@ -110,48 +105,18 @@
           o Passing blocks to #[]
           o Proc#lambda?
     * Enumerable and Enumerator
-          o Enumerable methods called without a block
-          o Enumerable#cycle
-          o Enumerable#each_with_index
-          o Enumerable#first(n)
-          o Enumerable#group_by
-          o Enumerable#find_index
-          o Enumerable#take
-          o Enumerable#drop
-          o Enumerable#take_while
-          o Enumerable#drop_while
-          o Enumerator#each
-          o Enumerable#inject (#reduce) without a block
-          o Enumerable#count
-          o Enumerable#reduce
-          o Enumerator#with_index
-          o Enumerable##min_by, #max_by
-          o Enumerable#zip
-          o Enumerable#minmax and minmax_by
-          o Enumerator#rewind
-          o Enumerator#next
+          o Enumerable#map,collect_all called without a block returns
+            an enumerator.
     * Regexp#match, String#match
           o Regexp#match, String#match
     * Fiber: coroutines/micro-threads
     * Array
-          o Block argument to Array#index, Array#rindex [Ruby2]
-          o Array#combination
-          o Array#permutation
-          o Array#product
-          o Array#pop, Array#shift
           o Array#to_s is equivalent to Array#inspect
           o Array.try_convert
     * Hash
           o preserving item insertion order
           o Hash#_compare_by_identity and Hash#compare_by_identity?
           o Hash.try_convert
-    * Integer
-          o Integer#odd?, #even?
-          o Integer#pred
-    * Method
-          o Method#receiver
-          o Method#name
-          o Method#owner
     * Numeric
           o Numeric#upto, #downto, #times, #step
           o Numeric#scalar?, Complex#scalar?
@@ -166,17 +131,11 @@
           o Regexp.try_convert
     * String
           o String#clear
-          o String#each_char
           o String#ord
-          o String#partition, #rpartition
-          o String#lines
-          o String#bytes
           o String#encoding
           o String#force_encoding
-          o String#start_with?, #end_with?
           o String#unpack with a block
           o String#hash
-          o String#upto
           o String.try_convert
 	  o String.encoding, String#force_encoding, String#encode
     * Symbol
@@ -190,16 +149,13 @@
     * File and Dir operations
           o New methods
     * Process
-          o Process.setrlimit
           o Process.daemon
-          o Process.exec
     * Misc. new methods
           o public_send
-          o GC.stress, GC.stress=, GC.count
+          o GC.count
           o ObjectSpace.count_objects
           o Method#hash, Proc#hash
-          o __method__ and __callee__
-          o Symbol#to_proc
+          o __callee__
 
 * Implementation
     * Memory Diet

Modified: MacRuby/branches/testing/encoding.c
===================================================================
--- MacRuby/branches/testing/encoding.c	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/encoding.c	2008-06-05 08:33:02 UTC (rev 249)
@@ -18,7 +18,7 @@
 #endif
 
 static ID id_encoding, id_base_encoding;
-static VALUE rb_cEncoding;
+VALUE rb_cEncoding;
 
 #if WITH_OBJC
 
@@ -82,6 +82,7 @@
 enc_make(const CFStringEncoding *enc)
 {
     VALUE v;
+    assert(enc != NULL);
     v = (VALUE)CFDictionaryGetValue( (CFDictionaryRef)__encodings, 
 	(const void *)(*enc));
     assert(v != 0);
@@ -415,17 +416,6 @@
 }
 #endif // WITH_OBJC
 
-int
-rb_enc_dummy_p(rb_encoding *enc)
-{
-#if WITH_OBJC
-    return Qfalse;
-#else
-    VALUE encoding = rb_enc_from_encoding(enc);
-    return ENC_DUMMY_P(encoding);
-#endif
-}
-
 /*
  * call-seq:
  *   enc.dummy? => true or false

Modified: MacRuby/branches/testing/enum.c
===================================================================
--- MacRuby/branches/testing/enum.c	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/enum.c	2008-06-05 08:33:02 UTC (rev 249)
@@ -2,7 +2,7 @@
 
   enum.c -
 
-  $Author: nobu $
+  $Author: knu $
   created at: Fri Oct  1 15:15:19 JST 1993
 
   Copyright (C) 1993-2007 Yukihiro Matsumoto
@@ -14,7 +14,7 @@
 #include "ruby/util.h"
 
 VALUE rb_mEnumerable;
-static ID id_each, id_eqq, id_cmp, id_next;
+static ID id_each, id_eqq, id_cmp, id_next, id_size;
 
 static VALUE
 enum_values_pack(int argc, VALUE *argv)
@@ -108,15 +108,29 @@
     return Qnil;
 }
 
+static VALUE
+count_all_i(VALUE i, VALUE memop, int argc, VALUE *argv)
+{
+    VALUE *memo = (VALUE*)memop;
+
+    memo[0]++;
+    return Qnil;
+}
+
 /*
  *  call-seq:
+ *     enum.count                   => int
  *     enum.count(item)             => int
  *     enum.count {| obj | block }  => int
  *
- *  Returns the number of items in <i>enum</i> for which equals to <i>item</i>.
- *  If a block is given, counts the number of elements yielding a true value.
+ *  Returns the number of items in <i>enum</i>, where #size is called
+ *  if it responds to it, otherwise the items are counted through
+ *  enumeration.  If an argument is given, counts the number of items
+ *  in <i>enum</i>, for which equals to <i>item</i>.  If a block is
+ *  given, counts the number of elements yielding a true value.
  *
  *     ary = [1, 2, 4, 2]
+ *     ary.count             # => 4
  *     ary.count(2)          # => 2
  *     ary.count{|x|x%2==0}  # => 3
  *
@@ -129,8 +143,15 @@
     rb_block_call_func *func;
 
     if (argc == 0) {
-	RETURN_ENUMERATOR(obj, 0, 0);
-        func = count_iter_i;
+	if (rb_block_given_p()) {
+	    func = count_iter_i;
+	}
+	else {
+	    if (rb_respond_to(obj, id_size)) {
+		return rb_funcall(obj, id_size, 0, 0);
+	    }
+	    func = count_all_i;
+	}
     }
     else {
 	rb_scan_args(argc, argv, "1", &memo[1]);
@@ -383,11 +404,11 @@
  *     { 'a'=>1, 'b'=>2, 'c'=>3 }.to_a   #=> [["a", 1], ["b", 2], ["c", 3]]
  */
 static VALUE
-enum_to_a(VALUE obj)
+enum_to_a(int argc, VALUE *argv, VALUE obj)
 {
     VALUE ary = rb_ary_new();
 
-    rb_block_call(obj, id_each, 0, 0, collect_all, ary);
+    rb_block_call(obj, id_each, argc, argv, collect_all, ary);
 
     return ary;
 }
@@ -657,7 +678,7 @@
 static VALUE
 enum_sort(VALUE obj)
 {
-    return rb_ary_sort(enum_to_a(obj));
+    return rb_ary_sort(enum_to_a(0, 0, obj));
 }
 
 static VALUE
@@ -685,10 +706,8 @@
 #else
     VALUE a = (*(NODE *const *)ap)->u1.value;
     VALUE b = (*(NODE *const *)bp)->u1.value;
-#endif
     VALUE ary = (VALUE)data;
-
-#if !WITH_OBJC
+    
     if (RBASIC(ary)->klass) {
 	rb_raise(rb_eRuntimeError, "sort_by reentered");
     }
@@ -1424,7 +1443,32 @@
 }
 
 
+/*
+ *  call-seq:
+ *     enum.reverse_each {|item| block } 
+ *  
+ *  Traverses <i>enum</i> in reverse order.
+ */
+
 static VALUE
+enum_reverse_each(int argc, VALUE *argv, VALUE obj)
+{
+    VALUE ary;
+    long i;
+
+    RETURN_ENUMERATOR(obj, argc, argv);
+
+    ary = enum_to_a(argc, argv, obj);
+
+    for (i = RARRAY_LEN(ary); --i >= 0; ) {
+	rb_yield(RARRAY_AT(ary, i));
+    }
+
+    return obj;
+}
+
+
+static VALUE
 zip_ary(VALUE val, NODE *memo, int argc, VALUE *argv)
 {
     volatile VALUE result = memo->u1.value;
@@ -1776,8 +1820,8 @@
 {
     rb_mEnumerable = rb_define_module("Enumerable");
 
-    rb_define_method(rb_mEnumerable,"to_a", enum_to_a, 0);
-    rb_define_method(rb_mEnumerable,"entries", enum_to_a, 0);
+    rb_define_method(rb_mEnumerable, "to_a", enum_to_a, -1);
+    rb_define_method(rb_mEnumerable, "entries", enum_to_a, -1);
 
     rb_define_method(rb_mEnumerable,"sort", enum_sort, 0);
     rb_define_method(rb_mEnumerable,"sort_by", enum_sort_by, 0);
@@ -1790,32 +1834,33 @@
 #else
     rb_define_method(rb_mEnumerable,"count", enum_count, -1);
 #endif
-    rb_define_method(rb_mEnumerable,"find", enum_find, -1);
-    rb_define_method(rb_mEnumerable,"detect", enum_find, -1);
-    rb_define_method(rb_mEnumerable,"find_index", enum_find_index, -1);
-    rb_define_method(rb_mEnumerable,"find_all", enum_find_all, 0);
-    rb_define_method(rb_mEnumerable,"select", enum_find_all, 0);
-    rb_define_method(rb_mEnumerable,"reject", enum_reject, 0);
-    rb_define_method(rb_mEnumerable,"collect", enum_collect, 0);
-    rb_define_method(rb_mEnumerable,"map", enum_collect, 0);
-    rb_define_method(rb_mEnumerable,"inject", enum_inject, -1);
-    rb_define_method(rb_mEnumerable,"reduce", enum_inject, -1);
-    rb_define_method(rb_mEnumerable,"partition", enum_partition, 0);
-    rb_define_method(rb_mEnumerable,"group_by", enum_group_by, 0);
-    rb_define_method(rb_mEnumerable,"first", enum_first, -1);
-    rb_define_method(rb_mEnumerable,"all?", enum_all, 0);
-    rb_define_method(rb_mEnumerable,"any?", enum_any, 0);
-    rb_define_method(rb_mEnumerable,"one?", enum_one, 0);
-    rb_define_method(rb_mEnumerable,"none?", enum_none, 0);
-    rb_define_method(rb_mEnumerable,"min", enum_min, 0);
-    rb_define_method(rb_mEnumerable,"max", enum_max, 0);
-    rb_define_method(rb_mEnumerable,"minmax", enum_minmax, 0);
-    rb_define_method(rb_mEnumerable,"min_by", enum_min_by, 0);
-    rb_define_method(rb_mEnumerable,"max_by", enum_max_by, 0);
-    rb_define_method(rb_mEnumerable,"minmax_by", enum_minmax_by, 0);
-    rb_define_method(rb_mEnumerable,"member?", enum_member, 1);
-    rb_define_method(rb_mEnumerable,"include?", enum_member, 1);
-    rb_define_method(rb_mEnumerable,"each_with_index", enum_each_with_index, -1);
+    rb_define_method(rb_mEnumerable, "find", enum_find, -1);
+    rb_define_method(rb_mEnumerable, "detect", enum_find, -1);
+    rb_define_method(rb_mEnumerable, "find_index", enum_find_index, -1);
+    rb_define_method(rb_mEnumerable, "find_all", enum_find_all, 0);
+    rb_define_method(rb_mEnumerable, "select", enum_find_all, 0);
+    rb_define_method(rb_mEnumerable, "reject", enum_reject, 0);
+    rb_define_method(rb_mEnumerable, "collect", enum_collect, 0);
+    rb_define_method(rb_mEnumerable, "map", enum_collect, 0);
+    rb_define_method(rb_mEnumerable, "inject", enum_inject, -1);
+    rb_define_method(rb_mEnumerable, "reduce", enum_inject, -1);
+    rb_define_method(rb_mEnumerable, "partition", enum_partition, 0);
+    rb_define_method(rb_mEnumerable, "group_by", enum_group_by, 0);
+    rb_define_method(rb_mEnumerable, "first", enum_first, -1);
+    rb_define_method(rb_mEnumerable, "all?", enum_all, 0);
+    rb_define_method(rb_mEnumerable, "any?", enum_any, 0);
+    rb_define_method(rb_mEnumerable, "one?", enum_one, 0);
+    rb_define_method(rb_mEnumerable, "none?", enum_none, 0);
+    rb_define_method(rb_mEnumerable, "min", enum_min, 0);
+    rb_define_method(rb_mEnumerable, "max", enum_max, 0);
+    rb_define_method(rb_mEnumerable, "minmax", enum_minmax, 0);
+    rb_define_method(rb_mEnumerable, "min_by", enum_min_by, 0);
+    rb_define_method(rb_mEnumerable, "max_by", enum_max_by, 0);
+    rb_define_method(rb_mEnumerable, "minmax_by", enum_minmax_by, 0);
+    rb_define_method(rb_mEnumerable, "member?", enum_member, 1);
+    rb_define_method(rb_mEnumerable, "include?", enum_member, 1);
+    rb_define_method(rb_mEnumerable, "each_with_index", enum_each_with_index, -1);
+    rb_define_method(rb_mEnumerable, "reverse_each", enum_reverse_each, -1);
     rb_define_method(rb_mEnumerable, "zip", enum_zip, -1);
     rb_define_method(rb_mEnumerable, "take", enum_take, 1);
     rb_define_method(rb_mEnumerable, "take_while", enum_take_while, 0);
@@ -1827,5 +1872,6 @@
     id_each = rb_intern("each");
     id_cmp  = rb_intern("<=>");
     id_next = rb_intern("next");
+    id_size = rb_intern("size");
 }
 

Modified: MacRuby/branches/testing/enumerator.c
===================================================================
--- MacRuby/branches/testing/enumerator.c	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/enumerator.c	2008-06-05 08:33:02 UTC (rev 249)
@@ -8,7 +8,7 @@
 
   $Idaemons: /home/cvs/rb/enumerator/enumerator.c,v 1.1.1.1 2001/07/15 10:12:48 knu Exp $
   $RoughId: enumerator.c,v 1.6 2003/07/27 11:03:24 nobu Exp $
-  $Id: enumerator.c 16402 2008-05-13 06:10:56Z knu $
+  $Id: enumerator.c 16614 2008-05-26 08:49:08Z knu $
 
 ************************************************/
 
@@ -30,7 +30,6 @@
     VALUE obj;
     ID    meth;
     VALUE args;
-    rb_block_call_func *iter;
     VALUE fib;
     VALUE dst;
     VALUE no_next;
@@ -39,11 +38,13 @@
 static void
 enumerator_mark(void *p)
 {
+#if !WITH_OBJC
     struct enumerator *ptr = p;
     rb_gc_mark(ptr->obj);
     rb_gc_mark(ptr->args);
     rb_gc_mark(ptr->fib);
     rb_gc_mark(ptr->dst);
+#endif
 }
 
 static struct enumerator *
@@ -54,8 +55,8 @@
     Data_Get_Struct(obj, struct enumerator, ptr);
     if (RDATA(obj)->dmark != enumerator_mark) {
 	rb_raise(rb_eTypeError,
-		 "wrong argument type %s (expected Enumerable::Enumerator)",
-		 rb_obj_classname(obj));
+		 "wrong argument type %s (expected %s)",
+		 rb_obj_classname(obj), rb_class2name(rb_cEnumerator));
     }
     if (!ptr) {
 	rb_raise(rb_eArgError, "uninitialized enumerator");
@@ -222,7 +223,6 @@
 
     ptr->obj  = obj;
     ptr->meth = rb_to_id(meth);
-    ptr->iter = enumerator_each_i;
     if (argc) GC_WB(&ptr->args, rb_ary_new4(argc, argv));
     ptr->fib = 0;
     ptr->dst = Qnil;
@@ -272,7 +272,6 @@
 
     ptr1->obj  = ptr0->obj;
     ptr1->meth = ptr0->meth;
-    ptr1->iter = ptr0->iter;
     ptr1->args = ptr0->args;
     ptr1->fib  = 0;
 
@@ -306,7 +305,8 @@
 	argc = RARRAY_LEN(e->args);
 	argv = RARRAY_PTR(e->args);
     }
-    return rb_block_call(e->obj, e->meth, argc, argv, e->iter, (VALUE)e);
+    return rb_block_call(e->obj, e->meth, argc, argv,
+			 enumerator_each_i, (VALUE)e);
 }
 
 static VALUE
@@ -329,12 +329,13 @@
 static VALUE
 enumerator_with_index(VALUE obj)
 {
-    struct enumerator *e = enumerator_ptr(obj);
+    struct enumerator *e;
     VALUE memo = 0;
     int argc = 0;
     const VALUE *argv = 0;
 
     RETURN_ENUMERATOR(obj, 0, 0);
+    e = enumerator_ptr(obj);
     if (e->args) {
 	argc = RARRAY_LEN(e->args);
 	argv = RARRAY_PTR(e->args);
@@ -438,6 +439,7 @@
     rb_define_method(rb_cEnumerator, "initialize", enumerator_initialize, -1);
     rb_define_method(rb_cEnumerator, "initialize_copy", enumerator_init_copy, 1);
     rb_define_method(rb_cEnumerator, "each", enumerator_each, 0);
+    rb_define_method(rb_cEnumerator, "each_with_index", enumerator_with_index, 0);
     rb_define_method(rb_cEnumerator, "with_index", enumerator_with_index, 0);
     rb_define_method(rb_cEnumerator, "next", enumerator_next, 0);
     rb_define_method(rb_cEnumerator, "rewind", enumerator_rewind, 0);

Modified: MacRuby/branches/testing/error.c
===================================================================
--- MacRuby/branches/testing/error.c	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/error.c	2008-06-05 08:33:02 UTC (rev 249)
@@ -2,7 +2,7 @@
 
   error.c -
 
-  $Author: nobu $
+  $Author: matz $
   created at: Mon Aug  9 16:11:34 JST 1993
 
   Copyright (C) 1993-2007 Yukihiro Matsumoto
@@ -556,7 +556,7 @@
 
     if (exc == obj) return Qtrue;
     if (rb_obj_class(exc) != rb_obj_class(obj))
-	return Qfalse;
+	return rb_equal(obj, exc);
     if (!rb_equal(rb_attr_get(exc, id_mesg), rb_attr_get(obj, id_mesg)))
 	return Qfalse;
     if (!rb_equal(exc_backtrace(exc), exc_backtrace(obj)))
@@ -963,18 +963,16 @@
 syserr_eqq(VALUE self, VALUE exc)
 {
     VALUE num, e;
+    ID en = rb_intern("errno");
 
-    if (!rb_obj_is_kind_of(exc, rb_eSystemCallError)) return Qfalse;
-    if (self == rb_eSystemCallError) return Qtrue;
+    if (!rb_obj_is_kind_of(exc, rb_eSystemCallError)) {
+	if (!rb_respond_to(exc, en)) return Qfalse;
+    }
+    else if (self == rb_eSystemCallError) return Qtrue;
 
     num = rb_attr_get(exc, rb_intern("errno"));
     if (NIL_P(num)) {
-	VALUE klass = CLASS_OF(exc);
-
-	while (TYPE(klass) == T_ICLASS || FL_TEST(klass, FL_SINGLETON)) {
-	    klass = (VALUE)RCLASS_SUPER(klass);
-	}
-	num = rb_const_get(klass, rb_intern("Errno"));
+	num = rb_funcall(exc, en, 0, 0);
     }
     e = rb_const_get(self, rb_intern("Errno"));
     if (FIXNUM_P(num) ? num == e : rb_equal(num, e))

Modified: MacRuby/branches/testing/eval.c
===================================================================
--- MacRuby/branches/testing/eval.c	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/eval.c	2008-06-05 08:33:02 UTC (rev 249)
@@ -2,7 +2,7 @@
 
   eval.c -
 
-  $Author: matz $
+  $Author: nobu $
   created at: Thu Jun 10 14:22:17 JST 1993
 
   Copyright (C) 1993-2007 Yukihiro Matsumoto
@@ -14,31 +14,19 @@
 #include "eval_intern.h"
 
 VALUE proc_invoke(VALUE, VALUE, VALUE, VALUE);
-VALUE rb_binding_new();
+VALUE rb_binding_new(void);
+NORETURN(void rb_raise_jump(VALUE));
 
 VALUE rb_f_block_given_p(void);
 
 ID rb_frame_callee(void);
-static VALUE rb_frame_self(void);
-
-static ID removed, singleton_removed, undefined, singleton_undefined;
-static ID init, eqq, each, aref, aset, match, missing;
-static ID added, singleton_added;
-static ID object_id, __send__, respond_to;
-
 VALUE rb_eLocalJumpError;
 VALUE rb_eSysStackError;
 VALUE sysstack_error;
 
 static VALUE exception_error;
 
-static VALUE eval(VALUE, VALUE, VALUE, const char *, int);
-
-static inline VALUE rb_yield_0(int argc, VALUE *argv);
-static VALUE rb_call(VALUE, VALUE, ID, int, const VALUE *, int);
-
 #include "eval_error.c"
-#include "eval_method.c"
 #include "eval_safe.c"
 #include "eval_jump.c"
 
@@ -106,7 +94,7 @@
 	error_print();
 	exit(EXIT_FAILURE);
     }
-    ruby_running = 1;
+    GET_VM()->running = 1;
 }
 
 extern void rb_clear_trace_func(void);
@@ -268,83 +256,6 @@
     return ruby_cleanup(ruby_exec_node(n, 0));
 }
 
-VALUE
-rb_eval_string(const char *str)
-{
-    return eval(rb_vm_top_self(), rb_str_new2(str), Qnil, "(eval)", 1);
-}
-
-VALUE
-rb_eval_string_protect(const char *str, int *state)
-{
-    return rb_protect((VALUE (*)(VALUE))rb_eval_string, (VALUE)str, state);
-}
-
-VALUE
-rb_eval_string_wrap(const char *str, int *state)
-{
-    int status;
-    rb_thread_t *th = GET_THREAD();
-    VALUE self = th->top_self;
-    VALUE wrapper = th->top_wrapper;
-    VALUE val;
-
-    th->top_wrapper = rb_module_new();
-    th->top_self = rb_obj_clone(rb_vm_top_self());
-    rb_extend_object(th->top_self, th->top_wrapper);
-
-    val = rb_eval_string_protect(str, &status);
-
-    th->top_self = self;
-    th->top_wrapper = wrapper;
-
-    if (state) {
-	*state = status;
-    }
-    else if (status) {
-	JUMP_TAG(status);
-    }
-    return val;
-}
-
-VALUE
-rb_eval_cmd(VALUE cmd, VALUE arg, int level)
-{
-    int state;
-    VALUE val = Qnil;		/* OK */
-    volatile int safe = rb_safe_level();
-
-    if (OBJ_TAINTED(cmd)) {
-	level = 4;
-    }
-
-    if (TYPE(cmd) != T_STRING) {
-	PUSH_TAG();
-	rb_set_safe_level_force(level);
-	if ((state = EXEC_TAG()) == 0) {
-	    val = rb_funcall2(cmd, rb_intern("call"), RARRAY_LEN(arg),
-			      RARRAY_PTR(arg));
-	}
-	POP_TAG();
-
-	rb_set_safe_level_force(safe);
-
-	if (state)
-	  JUMP_TAG(state);
-	return val;
-    }
-
-    PUSH_TAG();
-    if ((state = EXEC_TAG()) == 0) {
-	val = eval(rb_vm_top_self(), cmd, Qnil, 0, 0);
-    }
-    POP_TAG();
-
-    rb_set_safe_level_force(safe);
-    if (state) vm_jump_tag_but_local_jump(state, val);
-    return val;
-}
-
 /*
  *  call-seq:
  *     Module.nesting    => array
@@ -364,7 +275,7 @@
 rb_mod_nesting(void)
 {
     VALUE ary = rb_ary_new();
-    NODE *cref = ruby_cref();
+    const NODE *cref = vm_cref();
 
     while (cref && cref->nd_next) {
 	VALUE klass = cref->nd_clss;
@@ -393,7 +304,7 @@
 static VALUE
 rb_mod_s_constants(int argc, VALUE *argv, VALUE mod)
 {
-    NODE *cref = ruby_cref();
+    const NODE *cref = vm_cref();
     VALUE klass;
     VALUE cbase = 0;
     void *data = 0;
@@ -422,7 +333,7 @@
 void
 rb_frozen_class_p(VALUE klass)
 {
-    char *desc = "something(?!)";
+    const char *desc = "something(?!)";
 
     if (OBJ_FROZEN(klass)) {
 	if (FL_TEST(klass, FL_SINGLETON))
@@ -442,220 +353,8 @@
     }
 }
 
-/*
- *  call-seq:
- *     obj.respond_to?(symbol, include_private=false) => true or false
- *
- *  Returns +true+> if _obj_ responds to the given
- *  method. Private methods are included in the search only if the
- *  optional second parameter evaluates to +true+.
- */
-
-static NODE *basic_respond_to = 0;
-
-int
-rb_obj_respond_to(VALUE obj, ID id, int priv)
-{
-    VALUE klass = CLASS_OF(obj);
-
-    if (rb_method_node(klass, respond_to) == basic_respond_to) {
-	return rb_method_boundp(klass, id, !priv);
-    }
-    else {
-	VALUE args[2];
-	int n = 0;
-	args[n++] = ID2SYM(id);
-	if (priv)
-	    args[n++] = Qtrue;
-	return RTEST(rb_funcall2(obj, respond_to, n, args));
-    }
-}
-
-int
-rb_respond_to(VALUE obj, ID id)
-{
-    return rb_obj_respond_to(obj, id, Qfalse);
-}
-
-/*
- *  call-seq:
- *     obj.respond_to?(symbol, include_private=false) => true or false
- *
- *  Returns +true+> if _obj_ responds to the given
- *  method. Private methods are included in the search only if the
- *  optional second parameter evaluates to +true+.
- */
-
-static VALUE
-obj_respond_to(int argc, VALUE *argv, VALUE obj)
-{
-    VALUE mid, priv;
-    ID id;
-
-    rb_scan_args(argc, argv, "11", &mid, &priv);
-    id = rb_to_id(mid);
-    if (rb_method_boundp(CLASS_OF(obj), id, !RTEST(priv))) {
-	return Qtrue;
-    }
-    return Qfalse;
-}
-
-/*
- *  call-seq:
- *     mod.method_defined?(symbol)    => true or false
- *
- *  Returns +true+ if the named method is defined by
- *  _mod_ (or its included modules and, if _mod_ is a class,
- *  its ancestors). Public and protected methods are matched.
- *
- *     module A
- *       def method1()  end
- *     end
- *     class B
- *       def method2()  end
- *     end
- *     class C < B
- *       include A
- *       def method3()  end
- *     end
- *
- *     A.method_defined? :method1    #=> true
- *     C.method_defined? "method1"   #=> true
- *     C.method_defined? "method2"   #=> true
- *     C.method_defined? "method3"   #=> true
- *     C.method_defined? "method4"   #=> false
- */
-
-static VALUE
-rb_mod_method_defined(VALUE mod, VALUE mid)
-{
-    return rb_method_boundp(mod, rb_to_id(mid), 1);
-}
-
-#define VISI_CHECK(x,f) (((x)&NOEX_MASK) == (f))
-
-/*
- *  call-seq:
- *     mod.public_method_defined?(symbol)   => true or false
- *
- *  Returns +true+ if the named public method is defined by
- *  _mod_ (or its included modules and, if _mod_ is a class,
- *  its ancestors).
- *
- *     module A
- *       def method1()  end
- *     end
- *     class B
- *       protected
- *       def method2()  end
- *     end
- *     class C < B
- *       include A
- *       def method3()  end
- *     end
- *
- *     A.method_defined? :method1           #=> true
- *     C.public_method_defined? "method1"   #=> true
- *     C.public_method_defined? "method2"   #=> false
- *     C.method_defined? "method2"          #=> true
- */
-
-static VALUE
-rb_mod_public_method_defined(VALUE mod, VALUE mid)
-{
-    ID id = rb_to_id(mid);
-    NODE *method;
-
-    method = rb_method_node(mod, id);
-    if (method) {
-	if (VISI_CHECK(method->nd_noex, NOEX_PUBLIC))
-	    return Qtrue;
-    }
-    return Qfalse;
-}
-
-/*
- *  call-seq:
- *     mod.private_method_defined?(symbol)    => true or false
- *
- *  Returns +true+ if the named private method is defined by
- *  _ mod_ (or its included modules and, if _mod_ is a class,
- *  its ancestors).
- *
- *     module A
- *       def method1()  end
- *     end
- *     class B
- *       private
- *       def method2()  end
- *     end
- *     class C < B
- *       include A
- *       def method3()  end
- *     end
- *
- *     A.method_defined? :method1            #=> true
- *     C.private_method_defined? "method1"   #=> false
- *     C.private_method_defined? "method2"   #=> true
- *     C.method_defined? "method2"           #=> false
- */
-
-static VALUE
-rb_mod_private_method_defined(VALUE mod, VALUE mid)
-{
-    ID id = rb_to_id(mid);
-    NODE *method;
-
-    method = rb_method_node(mod, id);
-    if (method) {
-	if (VISI_CHECK(method->nd_noex, NOEX_PRIVATE))
-	    return Qtrue;
-    }
-    return Qfalse;
-}
-
-/*
- *  call-seq:
- *     mod.protected_method_defined?(symbol)   => true or false
- *
- *  Returns +true+ if the named protected method is defined
- *  by _mod_ (or its included modules and, if _mod_ is a
- *  class, its ancestors).
- *
- *     module A
- *       def method1()  end
- *     end
- *     class B
- *       protected
- *       def method2()  end
- *     end
- *     class C < B
- *       include A
- *       def method3()  end
- *     end
- *
- *     A.method_defined? :method1              #=> true
- *     C.protected_method_defined? "method1"   #=> false
- *     C.protected_method_defined? "method2"   #=> true
- *     C.method_defined? "method2"             #=> true
- */
-
-static VALUE
-rb_mod_protected_method_defined(VALUE mod, VALUE mid)
-{
-    ID id = rb_to_id(mid);
-    NODE *method;
-
-    method = rb_method_node(mod, id);
-    if (method) {
-	if (VISI_CHECK(method->nd_noex, NOEX_PROTECTED))
-	    return Qtrue;
-    }
-    return Qfalse;
-}
-
 NORETURN(static void rb_longjmp(int, VALUE));
-static VALUE make_backtrace(void);
+VALUE rb_make_backtrace(void);
 
 static void
 rb_longjmp(int tag, VALUE mesg)
@@ -682,7 +381,7 @@
     if (file && !NIL_P(mesg)) {
 	at = get_backtrace(mesg);
 	if (NIL_P(at)) {
-	    at = make_backtrace();
+	    at = rb_make_backtrace();
 	    set_backtrace(mesg, at);
 	}
     }
@@ -891,11 +590,12 @@
 
 
 VALUE
-rb_f_block_given_p()
+rb_f_block_given_p(void)
 {
     rb_thread_t *th = GET_THREAD();
     rb_control_frame_t *cfp = th->cfp;
     cfp = vm_get_ruby_level_cfp(th, RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp));
+
     if (GC_GUARDED_PTR_REF(cfp->lfp[0])) {
 	return Qtrue;
     }
@@ -914,202 +614,13 @@
     }
 }
 
-static inline VALUE
-rb_yield_0(int argc, VALUE *argv)
-{
-    return vm_yield(GET_THREAD(), argc, argv);
-}
-
 VALUE
-rb_yield(VALUE val)
+rb_rescue2(VALUE (* b_proc) (ANYARGS), VALUE data1,
+	   VALUE (* r_proc) (ANYARGS), VALUE data2, ...)
 {
-    volatile VALUE tmp = val;
-    if (val == Qundef) {
-	tmp = rb_yield_0(0, 0);
-    }
-    else {
-	tmp = rb_yield_0(1, &val);
-    }
-    return tmp;
-}
-
-VALUE
-rb_yield_values(int n, ...)
-{
-    int i;
-    VALUE *argv;
-    va_list args;
-
-    if (n == 0) {
-	return rb_yield_0(0, 0);
-    }
-
-    argv = ALLOCA_N(VALUE, n);
-
-    va_init_list(args, n);
-    for (i=0; i<n; i++) {
-	argv[i] = va_arg(args, VALUE);
-    }
-    va_end(args);
-
-    return rb_yield_0(n, argv);
-}
-
-VALUE
-rb_yield_values2(int argc, VALUE *argv)
-{
-    return rb_yield_0(argc, argv);
-}
-
-VALUE
-rb_yield_splat(VALUE values)
-{
-    VALUE tmp = rb_check_array_type(values);
-    volatile VALUE v;
-    if (NIL_P(tmp)) {
-        rb_raise(rb_eArgError, "not an array");
-    }
-    v = rb_yield_0(RARRAY_LEN(tmp), RARRAY_PTR(tmp));
-    return v;
-}
-
-static VALUE
-loop_i()
-{
-    for (;;) {
-	rb_yield_0(0, 0);
-    }
-    return Qnil;
-}
-
-/*
- *  call-seq:
- *     loop {|| block }
- *
- *  Repeatedly executes the block.
- *
- *     loop do
- *       print "Input: "
- *       line = gets
- *       break if !line or line =~ /^qQ/
- *       # ...
- *     end
- *
- *  StopIteration raised in the block breaks the loop.
- */
-
-static VALUE
-rb_f_loop(void)
-{
-    rb_rescue2(loop_i, (VALUE)0, 0, 0, rb_eStopIteration, (VALUE)0);
-    return Qnil;		/* dummy */
-}
-
-VALUE
-rb_iterate(VALUE (*it_proc) (VALUE), VALUE data1,
-	   VALUE (*bl_proc) (ANYARGS), VALUE data2)
-{
     int state;
-    volatile VALUE retval = Qnil;
-    NODE *node = NEW_IFUNC(bl_proc, data2);
     rb_thread_t *th = GET_THREAD();
     rb_control_frame_t *cfp = th->cfp;
-
-    TH_PUSH_TAG(th);
-    state = TH_EXEC_TAG();
-    if (state == 0) {
-      iter_retry:
-	{
-	    rb_block_t *blockptr = RUBY_VM_GET_BLOCK_PTR_IN_CFP(th->cfp);
-	    blockptr->iseq = (void *)node;
-	    blockptr->proc = 0;
-	    th->passed_block = blockptr;
-	}
-	retval = (*it_proc) (data1);
-    }
-    else {
-	VALUE err = th->errinfo;
-	if (state == TAG_BREAK) {
-	    VALUE *escape_dfp = GET_THROWOBJ_CATCH_POINT(err);
-	    VALUE *cdfp = cfp->dfp;
-
-	    if (cdfp == escape_dfp) {
-		state = 0;
-		th->state = 0;
-		th->errinfo = Qnil;
-		th->cfp = cfp;
-	    }
-	    else{
-		/* SDR(); printf("%p, %p\n", cdfp, escape_dfp); */
-	    }
-	}
-	else if (state == TAG_RETRY) {
-	    VALUE *escape_dfp = GET_THROWOBJ_CATCH_POINT(err);
-	    VALUE *cdfp = cfp->dfp;
-
-	    if (cdfp == escape_dfp) {
-		state = 0;
-		th->state = 0;
-		th->errinfo = Qnil;
-		th->cfp = cfp;
-		goto iter_retry;
-	    }
-	}
-    }
-    TH_POP_TAG();
-
-    switch (state) {
-      case 0:
-	break;
-      default:
-	TH_JUMP_TAG(th, state);
-    }
-    return retval;
-}
-
-struct iter_method_arg {
-    VALUE obj;
-    ID mid;
-    int argc;
-    VALUE *argv;
-};
-
-static VALUE
-iterate_method(VALUE obj)
-{
-    struct iter_method_arg *arg;
-
-    arg = (struct iter_method_arg *)obj;
-    return rb_call(CLASS_OF(arg->obj), arg->obj, arg->mid,
-		   arg->argc, arg->argv, CALL_FCALL);
-}
-
-VALUE
-rb_block_call(VALUE obj, ID mid, int argc, VALUE *argv,
-	      VALUE (*bl_proc) (ANYARGS), VALUE data2)
-{
-    struct iter_method_arg arg;
-
-    arg.obj = obj;
-    arg.mid = mid;
-    arg.argc = argc;
-    arg.argv = argv;
-    return rb_iterate(iterate_method, (VALUE)&arg, bl_proc, data2);
-}
-
-VALUE
-rb_each(VALUE obj)
-{
-    return rb_call(CLASS_OF(obj), obj, rb_intern("each"), 0, 0, CALL_FCALL);
-}
-
-VALUE
-rb_rescue2(VALUE (*b_proc) (ANYARGS), VALUE data1, VALUE (*r_proc) (ANYARGS),
-	   VALUE data2, ...)
-{
-    int state;
-    rb_thread_t *th = GET_THREAD();
-    rb_control_frame_t *cfp = th->cfp;
     volatile VALUE result;
     volatile VALUE e_info = th->errinfo;
     va_list args;
@@ -1166,14 +677,15 @@
 }
 
 VALUE
-rb_rescue(VALUE (*b_proc)(ANYARGS), VALUE data1, VALUE (*r_proc)(ANYARGS), VALUE data2)
+rb_rescue(VALUE (* b_proc)(ANYARGS), VALUE data1,
+	  VALUE (* r_proc)(ANYARGS), VALUE data2)
 {
     return rb_rescue2(b_proc, data1, r_proc, data2, rb_eStandardError,
 		      (VALUE)0);
 }
 
 VALUE
-rb_protect(VALUE (*proc) (VALUE), VALUE data, int *state)
+rb_protect(VALUE (* proc) (VALUE), VALUE data, int * state)
 {
     VALUE result = Qnil;	/* OK */
     int status;
@@ -1249,415 +761,6 @@
     return result;
 }
 
-static inline void
-stack_check(void)
-{
-    rb_thread_t *th = GET_THREAD();
-
-    if (!rb_thread_raised_p(th, RAISED_STACKOVERFLOW) && ruby_stack_check()) {
-	rb_thread_raised_set(th, RAISED_STACKOVERFLOW);
-	rb_exc_raise(sysstack_error);
-    }
-}
-
-/*
- *  call-seq:
- *     obj.method_missing(symbol [, *args] )   => result
- *
- *  Invoked by Ruby when <i>obj</i> is sent a message it cannot handle.
- *  <i>symbol</i> is the symbol for the method called, and <i>args</i>
- *  are any arguments that were passed to it. By default, the interpreter
- *  raises an error when this method is called. However, it is possible
- *  to override the method to provide more dynamic behavior.
- *  If it is decided that a particular method should not be handled, then
- *  <i>super</i> should be called, so that ancestors can pick up the
- *  missing method.
- *  The example below creates
- *  a class <code>Roman</code>, which responds to methods with names
- *  consisting of roman numerals, returning the corresponding integer
- *  values.
- *
- *     class Roman
- *       def romanToInt(str)
- *         # ...
- *       end
- *       def method_missing(methId)
- *         str = methId.id2name
- *         romanToInt(str)
- *       end
- *     end
- *
- *     r = Roman.new
- *     r.iv      #=> 4
- *     r.xxiii   #=> 23
- *     r.mm      #=> 2000
- */
-
-static VALUE
-rb_method_missing(int argc, const VALUE *argv, VALUE obj)
-{
-    ID id;
-    VALUE exc = rb_eNoMethodError;
-    char *format = 0;
-    rb_thread_t *th = GET_THREAD();
-    int last_call_status = th->method_missing_reason;
-    if (argc == 0 || !SYMBOL_P(argv[0])) {
-	rb_raise(rb_eArgError, "no id given");
-    }
-
-    stack_check();
-
-    id = SYM2ID(argv[0]);
-
-    if (last_call_status & NOEX_PRIVATE) {
-	format = "private method `%s' called for %s";
-    }
-    else if (last_call_status & NOEX_PROTECTED) {
-	format = "protected method `%s' called for %s";
-    }
-    else if (last_call_status & NOEX_VCALL) {
-	format = "undefined local variable or method `%s' for %s";
-	exc = rb_eNameError;
-    }
-    else if (last_call_status & NOEX_SUPER) {
-	format = "super: no superclass method `%s' for %s";
-    }
-    if (!format) {
-	format = "undefined method `%s' for %s";
-    }
-
-    {
-	int n = 0;
-	VALUE args[3];
-	args[n++] = rb_funcall(rb_const_get(exc, rb_intern("message")), '!',
-			       3, rb_str_new2(format), obj, argv[0]);
-	args[n++] = argv[0];
-	if (exc == rb_eNoMethodError) {
-	    args[n++] = rb_ary_new4(argc - 1, argv + 1);
-	}
-	exc = rb_class_new_instance(n, args, exc);
-
-	th->cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(th->cfp);
-	rb_exc_raise(exc);
-    }
-
-    return Qnil;		/* not reached */
-}
-
-static VALUE
-method_missing(VALUE obj, ID id, int argc, const VALUE *argv, int call_status)
-{
-    VALUE *nargv;
-    GET_THREAD()->method_missing_reason = call_status;
-
-    if (id == missing) {
-	rb_method_missing(argc, argv, obj);
-    }
-    else if (id == ID_ALLOCATOR) {
-	rb_raise(rb_eTypeError, "allocator undefined for %s",
-		 rb_class2name(obj));
-    }
-
-    nargv = ALLOCA_N(VALUE, argc + 1);
-    nargv[0] = ID2SYM(id);
-    MEMCPY(nargv + 1, argv, VALUE, argc);
-
-    return rb_funcall2(obj, missing, argc + 1, nargv);
-}
-
-static VALUE
-rb_call0(VALUE klass, VALUE recv, ID mid, int argc, const VALUE *argv, int scope, VALUE self)
-{
-    NODE *body, *method;
-    int noex;
-    ID id = mid;
-    struct cache_entry *ent;
-    rb_thread_t *th = GET_THREAD();
-#if WITH_OBJC
-    unsigned redo = 0;
-#endif
-
-rb_call0_redo:
-
-#if WITH_OBJC
-# define REDO_PERHAPS() \
-    if (!redo) { \
-	ID newid = rb_objc_missing_sel(mid, argc); \
-	if (newid != mid) { \
-	    id = mid = newid; \
-	    redo = 1; \
-	    goto rb_call0_redo; \
-	} \
-    } 
-#else
-# define REDO_PERHAPS()
-#endif
-
-    if (!klass) {
-	rb_raise(rb_eNotImpError,
-		 "method `%s' called on terminated object (%p)",
-		 rb_id2name(mid), (void *)recv);
-    }
-    /* is it in the method cache? */
-    ent = cache + EXPR1(klass, mid);
-
-    if (ent->mid == mid && ent->klass == klass) {
-	if (!ent->method) {
-	    REDO_PERHAPS();
-	    return method_missing(recv, mid, argc, argv,
-				  scope == 2 ? NOEX_VCALL : 0);
-	}
-	id = ent->mid0;
-	noex = ent->method->nd_noex;
-	klass = ent->method->nd_clss;
-	body = ent->method->nd_body;
-    }
-    else if ((method = rb_get_method_body(klass, id, &id)) != 0) {
-	noex = method->nd_noex;
-	klass = method->nd_clss;
-	body = method->nd_body;
-    }
-    else {
-	REDO_PERHAPS();
-	if (scope == 3) {
-	    return method_missing(recv, mid, argc, argv, NOEX_SUPER);
-	}
-	return method_missing(recv, mid, argc, argv,
-			      scope == 2 ? NOEX_VCALL : 0);
-    }
-    
-
-    if (mid != missing) {
-	/* receiver specified form for private method */
-	if (UNLIKELY(noex)) {
-	    if (((noex & NOEX_MASK) & NOEX_PRIVATE) && scope == 0) {
-		return method_missing(recv, mid, argc, argv, NOEX_PRIVATE);
-	    }
-
-	    /* self must be kind of a specified form for protected method */
-	    if (((noex & NOEX_MASK) & NOEX_PROTECTED) && scope == 0) {
-		VALUE defined_class = klass;
-		
-		if (TYPE(defined_class) == T_ICLASS) {
-		    defined_class = RBASIC(defined_class)->klass;
-		}
-		
-		if (self == Qundef) {
-		    self = rb_frame_self();
-		}
-		if (!rb_obj_is_kind_of(self, rb_class_real(defined_class))) {
-		    return method_missing(recv, mid, argc, argv, NOEX_PROTECTED);
-		}
-	    }
-
-	    if (NOEX_SAFE(noex) > th->safe_level) {
-		rb_raise(rb_eSecurityError, "calling insecure method: %s", rb_id2name(mid));
-	    }
-	}
-    }
-
-    stack_check();
-
-    {
-	VALUE val;
-	/*
-	//static int level;
-	//int i;
-	//for(i=0; i<level; i++){printf("  ");}
-	//printf("invoke %s (%s)\n", rb_id2name(mid), ruby_node_name(nd_type(body)));
-	//level++;
-	//printf("%s with %d args\n", rb_id2name(mid), argc);
-	*/
-	val = vm_call0(th, klass, recv, mid, id, argc, argv, body,
-		       noex & NOEX_NOSUPER);
-	/*
-	//level--;
-	//for(i=0; i<level; i++){printf("  ");}
-	//printf("done %s (%s)\n", rb_id2name(mid), ruby_node_name(nd_type(body)));
-	*/
-	return val;
-    }
-
-#undef REDO_PERHAPS
-}
-
-static VALUE
-rb_call(VALUE klass, VALUE recv, ID mid, int argc, const VALUE *argv, int scope)
-{
-    return rb_call0(klass, recv, mid, argc, argv, scope, Qundef);
-}
-
-VALUE
-rb_apply(VALUE recv, ID mid, VALUE args)
-{
-    int argc;
-    VALUE *argv;
-
-    argc = RARRAY_LEN(args);	/* Assigns LONG, but argc is INT */
-    argv = ALLOCA_N(VALUE, argc);
-    MEMCPY(argv, RARRAY_PTR(args), VALUE, argc);
-    return rb_call(CLASS_OF(recv), recv, mid, argc, argv, CALL_FCALL);
-}
-
-static VALUE
-send_internal(int argc, VALUE *argv, VALUE recv, int scope)
-{
-    VALUE vid;
-    VALUE self = RUBY_VM_PREVIOUS_CONTROL_FRAME(GET_THREAD()->cfp)->self;
-
-    if (argc == 0) {
-	rb_raise(rb_eArgError, "no method name given");
-    }
-
-    vid = *argv++; argc--;
-    PASS_PASSED_BLOCK();
-    return rb_call0(CLASS_OF(recv), recv, rb_to_id(vid), argc, argv, scope, self);
-}
-
-/*
- *  call-seq:
- *     obj.send(symbol [, args...])        => obj
- *     obj.__send__(symbol [, args...])      => obj
- *
- *  Invokes the method identified by _symbol_, passing it any
- *  arguments specified. You can use <code>__send__</code> if the name
- *  +send+ clashes with an existing method in _obj_.
- *
- *     class Klass
- *       def hello(*args)
- *         "Hello " + args.join(' ')
- *       end
- *     end
- *     k = Klass.new
- *     k.send :hello, "gentle", "readers"   #=> "Hello gentle readers"
- */
-
-VALUE
-rb_f_send(int argc, VALUE *argv, VALUE recv)
-{
-    return send_internal(argc, argv, recv, NOEX_NOSUPER | NOEX_PRIVATE);
-}
-
-
-/*
- *  call-seq:
- *     obj.public_send(symbol [, args...])  => obj
- *
- *  Invokes the method identified by _symbol_, passing it any
- *  arguments specified. Unlike send, public_send calls public
- *  methods only.
- *
- *     1.public_send(:puts, "hello")  # causes NoMethodError
- */
-
-VALUE
-rb_f_public_send(int argc, VALUE *argv, VALUE recv)
-{
-    return send_internal(argc, argv, recv, NOEX_PUBLIC);
-}
-
-VALUE
-rb_funcall(VALUE recv, ID mid, int n, ...)
-{
-    VALUE *argv;
-    va_list ar;
-    va_init_list(ar, n);
-
-    if (n > 0) {
-	long i;
-
-	argv = ALLOCA_N(VALUE, n);
-
-	for (i = 0; i < n; i++) {
-	    argv[i] = va_arg(ar, VALUE);
-	}
-	va_end(ar);
-    }
-    else {
-	argv = 0;
-    }
-    return rb_call(CLASS_OF(recv), recv, mid, n, argv, CALL_FCALL);
-}
-
-VALUE
-rb_funcall2(VALUE recv, ID mid, int argc, const VALUE *argv)
-{
-    return rb_call(CLASS_OF(recv), recv, mid, argc, argv, CALL_FCALL);
-}
-
-VALUE
-rb_funcall3(VALUE recv, ID mid, int argc, const VALUE *argv)
-{
-    return rb_call(CLASS_OF(recv), recv, mid, argc, argv, CALL_PUBLIC);
-}
-
-static VALUE
-backtrace(int lev)
-{
-    return vm_backtrace(GET_THREAD(), lev);
-}
-
-/*
- *  call-seq:
- *     caller(start=1)    => array
- *
- *  Returns the current execution stack---an array containing strings in
- *  the form ``<em>file:line</em>'' or ``<em>file:line: in
- *  `method'</em>''. The optional _start_ parameter
- *  determines the number of initial stack entries to omit from the
- *  result.
- *
- *     def a(skip)
- *       caller(skip)
- *     end
- *     def b(skip)
- *       a(skip)
- *     end
- *     def c(skip)
- *       b(skip)
- *     end
- *     c(0)   #=> ["prog:2:in `a'", "prog:5:in `b'", "prog:8:in `c'", "prog:10"]
- *     c(1)   #=> ["prog:5:in `b'", "prog:8:in `c'", "prog:11"]
- *     c(2)   #=> ["prog:8:in `c'", "prog:12"]
- *     c(3)   #=> ["prog:13"]
- */
-
-static VALUE
-rb_f_caller(int argc, VALUE *argv)
-{
-    VALUE level;
-    int lev;
-
-    rb_scan_args(argc, argv, "01", &level);
-
-    if (NIL_P(level))
-	lev = 1;
-    else
-	lev = NUM2INT(level);
-    if (lev < 0)
-	rb_raise(rb_eArgError, "negative level (%d)", lev);
-
-    return backtrace(lev);
-}
-
-void
-rb_backtrace(void)
-{
-    long i;
-    VALUE ary;
-
-    ary = backtrace(-1);
-    for (i = 0; i < RARRAY_LEN(ary); i++) {
-	printf("\tfrom %s\n", RSTRING_CPTR(RARRAY_AT(ary, i)));
-    }
-}
-
-static VALUE
-make_backtrace(void)
-{
-    return backtrace(-1);
-}
-
 static ID
 frame_func_id(rb_control_frame_t *cfp)
 {
@@ -1705,659 +808,8 @@
     th->cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(th->cfp);
 }
 
-static VALUE
-rb_frame_self(void)
-{
-    return GET_THREAD()->cfp->self;
-}
-
-static VALUE
-eval(VALUE self, VALUE src, VALUE scope, const char *file, int line)
-{
-    int state;
-    VALUE result = Qundef;
-    VALUE envval;
-    rb_binding_t *bind = 0;
-    rb_thread_t *th = GET_THREAD();
-    rb_env_t *env = NULL;
-    NODE *stored_cref_stack = 0;
-
-    if (file == 0) {
-	file = rb_sourcefile();
-	line = rb_sourceline();
-    }
-
-    PUSH_TAG();
-    if ((state = EXEC_TAG()) == 0) {
-	rb_iseq_t *iseq;
-	volatile VALUE iseqval;
-
-	if (scope != Qnil) {
-	    if (rb_obj_is_kind_of(scope, rb_cBinding)) {
-		GetBindingPtr(scope, bind);
-		envval = bind->env;
-		stored_cref_stack = bind->cref_stack;
-	    }
-	    else {
-		rb_raise(rb_eTypeError,
-			 "wrong argument type %s (expected Binding)",
-			 rb_obj_classname(scope));
-	    }
-	    GetEnvPtr(envval, env);
-	    th->base_block = &env->block;
-	}
-	else {
-	    rb_control_frame_t *cfp = vm_get_ruby_level_cfp(th, th->cfp);
-	    th->base_block = RUBY_VM_GET_BLOCK_PTR_IN_CFP(cfp);
-	    th->base_block->iseq = cfp->iseq;	/* TODO */
-	}
-
-	/* make eval iseq */
-	th->parse_in_eval++;
-	iseqval = rb_iseq_compile(src, rb_str_new2(file), INT2FIX(line));
-	th->parse_in_eval--;
-	rb_vm_set_eval_stack(th, iseqval);
-	th->base_block = 0;
-
-	if (0) {		/* for debug */
-	    extern VALUE ruby_iseq_disasm(VALUE);
-	    printf("%s\n", RSTRING_CPTR(ruby_iseq_disasm(iseqval)));
-	}
-
-	/* save new env */
-	GetISeqPtr(iseqval, iseq);
-	if (bind && iseq->local_size > 0) {
-	    bind->env = vm_make_env_object(th, th->cfp);
-	}
-
-	/* push tag */
-	if (stored_cref_stack) {
-	    stored_cref_stack =
-	      vm_set_special_cref(th, env->block.lfp, stored_cref_stack);
-	}
-
-	/* kick */
-	CHECK_STACK_OVERFLOW(th->cfp, iseq->stack_max);
-	result = vm_eval_body(th);
-    }
-    POP_TAG();
-
-    if (stored_cref_stack) {
-	vm_set_special_cref(th, env->block.lfp, stored_cref_stack);
-    }
-
-    if (state) {
-	if (state == TAG_RAISE) {
-	    VALUE errinfo = th->errinfo;
-	    if (strcmp(file, "(eval)") == 0) {
-		VALUE mesg, errat, bt2;
-
-		errat = get_backtrace(errinfo);
-		mesg = rb_attr_get(errinfo, rb_intern("mesg"));
-		if (!NIL_P(errat) && TYPE(errat) == T_ARRAY &&
-		    (bt2 = backtrace(-2), RARRAY_LEN(bt2) > 0)) {
-		    if (!NIL_P(mesg) && TYPE(mesg) == T_STRING && !RSTRING_CLEN(mesg)) {
-			rb_str_update(mesg, 0, 0, rb_str_new2(": "));
-			rb_str_update(mesg, 0, 0, RARRAY_AT(errat, 0));
-		    }
-		    rb_ary_store(errat, 0, RARRAY_AT(bt2, 0));
-		}
-	    }
-	    rb_exc_raise(errinfo);
-	}
-	JUMP_TAG(state);
-    }
-    return result;
-}
-
 /*
  *  call-seq:
- *     eval(string [, binding [, filename [,lineno]]])  => obj
- *
- *  Evaluates the Ruby expression(s) in <em>string</em>. If
- *  <em>binding</em> is given, the evaluation is performed in its
- *  context. The binding may be a <code>Binding</code> object or a
- *  <code>Proc</code> object. If the optional <em>filename</em> and
- *  <em>lineno</em> parameters are present, they will be used when
- *  reporting syntax errors.
- *
- *     def getBinding(str)
- *       return binding
- *     end
- *     str = "hello"
- *     eval "str + ' Fred'"                      #=> "hello Fred"
- *     eval "str + ' Fred'", getBinding("bye")   #=> "bye Fred"
- */
-
-VALUE
-rb_f_eval(int argc, VALUE *argv, VALUE self)
-{
-    VALUE src, scope, vfile, vline;
-    const char *file = "(eval)";
-    int line = 1;
-
-    rb_scan_args(argc, argv, "13", &src, &scope, &vfile, &vline);
-    if (rb_safe_level() >= 4) {
-	StringValue(src);
-	if (!NIL_P(scope) && !OBJ_TAINTED(scope)) {
-	    rb_raise(rb_eSecurityError,
-		     "Insecure: can't modify trusted binding");
-	}
-    }
-    else {
-	SafeStringValue(src);
-    }
-    if (argc >= 3) {
-	StringValue(vfile);
-    }
-    if (argc >= 4) {
-	line = NUM2INT(vline);
-    }
-
-    if (!NIL_P(vfile))
-	file = RSTRING_CPTR(vfile);
-    return eval(self, src, scope, file, line);
-}
-
-VALUE vm_cfp_svar_get(rb_thread_t *th, rb_control_frame_t *cfp, VALUE key);
-void vm_cfp_svar_set(rb_thread_t *th, rb_control_frame_t *cfp, VALUE key, VALUE val);
-
-/* function to call func under the specified class/module context */
-static VALUE
-exec_under(VALUE (*func) (VALUE), VALUE under, VALUE self, VALUE args)
-{
-    VALUE val = Qnil;		/* OK */
-    rb_thread_t *th = GET_THREAD();
-    rb_control_frame_t *cfp = th->cfp;
-    rb_control_frame_t *pcfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
-    VALUE stored_self = pcfp->self;
-    NODE *stored_cref = 0;
-
-    rb_block_t block;
-    rb_block_t *blockptr;
-    int state;
-
-    /* replace environment */
-    pcfp->self = self;
-    if ((blockptr = GC_GUARDED_PTR_REF(*th->cfp->lfp)) != 0) {
-	/* copy block info */
-	/* TODO: why? */
-	block = *blockptr;
-	block.self = self;
-	*th->cfp->lfp = GC_GUARDED_PTR(&block);
-    }
-
-    while (!RUBY_VM_NORMAL_ISEQ_P(cfp->iseq)) {
-	cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
-    }
-
-    stored_cref = (NODE *)vm_cfp_svar_get(th, cfp, 2);
-    vm_cfp_svar_set(th, cfp, 2, (VALUE)vm_cref_push(th, under, NOEX_PUBLIC));
-
-    PUSH_TAG();
-    if ((state = EXEC_TAG()) == 0) {
-	val = (*func) (args);
-    }
-    POP_TAG();
-
-    /* restore environment */
-    vm_cfp_svar_set(th, cfp, 2, (VALUE)stored_cref);
-    pcfp->self = stored_self;
-
-    if (state) {
-	JUMP_TAG(state);
-    }
-    return val;
-}
-
-static VALUE
-yield_under_i(VALUE arg)
-{
-    if (arg == Qundef) {
-	return rb_yield_0(0, 0);
-    }
-    else {
-	return rb_yield_0(RARRAY_LEN(arg), RARRAY_PTR(arg));
-    }
-}
-
-/* block eval under the class/module context */
-static VALUE
-yield_under(VALUE under, VALUE self, VALUE values)
-{
-    return exec_under(yield_under_i, under, self, values);
-}
-
-static VALUE
-eval_under_i(VALUE arg)
-{
-    VALUE *args = (VALUE *)arg;
-    return eval(args[0], args[1], Qnil, (char *)args[2], (int)args[3]);
-}
-
-/* string eval under the class/module context */
-static VALUE
-eval_under(VALUE under, VALUE self, VALUE src, const char *file, int line)
-{
-    VALUE args[4];
-
-    if (rb_safe_level() >= 4) {
-	StringValue(src);
-    }
-    else {
-	SafeStringValue(src);
-    }
-    args[0] = self;
-    args[1] = src;
-    args[2] = (VALUE)file;
-    args[3] = (VALUE)line;
-    return exec_under(eval_under_i, under, self, (VALUE)args);
-}
-
-static VALUE
-specific_eval(int argc, VALUE *argv, VALUE klass, VALUE self)
-{
-    if (rb_block_given_p()) {
-	if (argc > 0) {
-	    rb_raise(rb_eArgError, "wrong number of arguments (%d for 0)",
-		     argc);
-	}
-	return yield_under(klass, self, Qundef);
-    }
-    else {
-	char *file = "(eval)";
-	int line = 1;
-
-	if (argc == 0) {
-	    rb_raise(rb_eArgError, "block not supplied");
-	}
-	else {
-	    if (rb_safe_level() >= 4) {
-		StringValue(argv[0]);
-	    }
-	    else {
-		SafeStringValue(argv[0]);
-	    }
-	    if (argc > 3) {
-		const char *name = rb_id2name(rb_frame_callee());
-		rb_raise(rb_eArgError,
-			 "wrong number of arguments: %s(src) or %s{..}",
-			 name, name);
-	    }
-	    if (argc > 2)
-		line = NUM2INT(argv[2]);
-	    if (argc > 1) {
-		file = StringValuePtr(argv[1]);
-	    }
-	}
-	return eval_under(klass, self, argv[0], file, line);
-    }
-}
-
-/*
- *  call-seq:
- *     obj.instance_eval(string [, filename [, lineno]] )   => obj
- *     obj.instance_eval {| | block }                       => obj
- *
- *  Evaluates a string containing Ruby source code, or the given block,
- *  within the context of the receiver (_obj_). In order to set the
- *  context, the variable +self+ is set to _obj_ while
- *  the code is executing, giving the code access to _obj_'s
- *  instance variables. In the version of <code>instance_eval</code>
- *  that takes a +String+, the optional second and third
- *  parameters supply a filename and starting line number that are used
- *  when reporting compilation errors.
- *
- *     class KlassWithSecret
- *       def initialize
- *         @secret = 99
- *       end
- *     end
- *     k = KlassWithSecret.new
- *     k.instance_eval { @secret }   #=> 99
- */
-
-VALUE
-rb_obj_instance_eval(int argc, VALUE *argv, VALUE self)
-{
-    VALUE klass;
-
-    if (SPECIAL_CONST_P(self)) {
-	klass = CLASS_OF(self); /* klass = Qnil; */
-    }
-    else {
-	klass = rb_singleton_class(self);
-    }
-    return specific_eval(argc, argv, klass, self);
-}
-
-/*
- *  call-seq:
- *     obj.instance_exec(arg...) {|var...| block }                       => obj
- *
- *  Executes the given block within the context of the receiver
- *  (_obj_). In order to set the context, the variable +self+ is set
- *  to _obj_ while the code is executing, giving the code access to
- *  _obj_'s instance variables.  Arguments are passed as block parameters.
- *
- *     class KlassWithSecret
- *       def initialize
- *         @secret = 99
- *       end
- *     end
- *     k = KlassWithSecret.new
- *     k.instance_exec(5) {|x| @secret+x }   #=> 104
- */
-
-VALUE
-rb_obj_instance_exec(int argc, VALUE *argv, VALUE self)
-{
-    VALUE klass;
-
-    if (SPECIAL_CONST_P(self)) {
-	klass = Qnil;
-    }
-    else {
-	klass = rb_singleton_class(self);
-    }
-    return yield_under(klass, self, rb_ary_new4(argc, argv));
-}
-
-/*
- *  call-seq:
- *     mod.class_eval(string [, filename [, lineno]])  => obj
- *     mod.module_eval {|| block }                     => obj
- *
- *  Evaluates the string or block in the context of _mod_. This can
- *  be used to add methods to a class. <code>module_eval</code> returns
- *  the result of evaluating its argument. The optional _filename_
- *  and _lineno_ parameters set the text for error messages.
- *
- *     class Thing
- *     end
- *     a = %q{def hello() "Hello there!" end}
- *     Thing.module_eval(a)
- *     puts Thing.new.hello()
- *     Thing.module_eval("invalid code", "dummy", 123)
- *
- *  <em>produces:</em>
- *
- *     Hello there!
- *     dummy:123:in `module_eval': undefined local variable
- *         or method `code' for Thing:Class
- */
-
-VALUE
-rb_mod_module_eval(int argc, VALUE *argv, VALUE mod)
-{
-    return specific_eval(argc, argv, mod, mod);
-}
-
-/*
- *  call-seq:
- *     mod.module_exec(arg...) {|var...| block }       => obj
- *     mod.class_exec(arg...) {|var...| block }        => obj
- *
- *  Evaluates the given block in the context of the class/module.
- *  The method defined in the block will belong to the receiver.
- *
- *     class Thing
- *     end
- *     Thing.class_exec{
- *       def hello() "Hello there!" end
- *     }
- *     puts Thing.new.hello()
- *
- *  <em>produces:</em>
- *
- *     Hello there!
- */
-
-VALUE
-rb_mod_module_exec(int argc, VALUE *argv, VALUE mod)
-{
-    return yield_under(mod, mod, rb_ary_new4(argc, argv));
-}
-
-static void
-secure_visibility(VALUE self)
-{
-    if (rb_safe_level() >= 4 && !OBJ_TAINTED(self)) {
-	rb_raise(rb_eSecurityError,
-		 "Insecure: can't change method visibility");
-    }
-}
-
-static void
-set_method_visibility(VALUE self, int argc, VALUE *argv, ID ex)
-{
-    int i;
-    secure_visibility(self);
-    for (i = 0; i < argc; i++) {
-	rb_export_method(self, rb_to_id(argv[i]), ex);
-    }
-    rb_clear_cache_by_class(self);
-}
-
-/*
- *  call-seq:
- *     public                 => self
- *     public(symbol, ...)    => self
- *
- *  With no arguments, sets the default visibility for subsequently
- *  defined methods to public. With arguments, sets the named methods to
- *  have public visibility.
- */
-
-static VALUE
-rb_mod_public(int argc, VALUE *argv, VALUE module)
-{
-    secure_visibility(module);
-    if (argc == 0) {
-	SCOPE_SET(NOEX_PUBLIC);
-    }
-    else {
-	set_method_visibility(module, argc, argv, NOEX_PUBLIC);
-    }
-    return module;
-}
-
-/*
- *  call-seq:
- *     protected                => self
- *     protected(symbol, ...)   => self
- *
- *  With no arguments, sets the default visibility for subsequently
- *  defined methods to protected. With arguments, sets the named methods
- *  to have protected visibility.
- */
-
-static VALUE
-rb_mod_protected(int argc, VALUE *argv, VALUE module)
-{
-    secure_visibility(module);
-    if (argc == 0) {
-	SCOPE_SET(NOEX_PROTECTED);
-    }
-    else {
-	set_method_visibility(module, argc, argv, NOEX_PROTECTED);
-    }
-    return module;
-}
-
-/*
- *  call-seq:
- *     private                 => self
- *     private(symbol, ...)    => self
- *
- *  With no arguments, sets the default visibility for subsequently
- *  defined methods to private. With arguments, sets the named methods
- *  to have private visibility.
- *
- *     module Mod
- *       def a()  end
- *       def b()  end
- *       private
- *       def c()  end
- *       private :a
- *     end
- *     Mod.private_instance_methods   #=> [:a, :c]
- */
-
-static VALUE
-rb_mod_private(int argc, VALUE *argv, VALUE module)
-{
-    secure_visibility(module);
-    if (argc == 0) {
-	SCOPE_SET(NOEX_PRIVATE);
-    }
-    else {
-	set_method_visibility(module, argc, argv, NOEX_PRIVATE);
-    }
-    return module;
-}
-
-/*
- *  call-seq:
- *     mod.public_class_method(symbol, ...)    => mod
- *
- *  Makes a list of existing class methods public.
- */
-
-static VALUE
-rb_mod_public_method(int argc, VALUE *argv, VALUE obj)
-{
-    set_method_visibility(CLASS_OF(obj), argc, argv, NOEX_PUBLIC);
-    return obj;
-}
-
-/*
- *  call-seq:
- *     mod.private_class_method(symbol, ...)   => mod
- *
- *  Makes existing class methods private. Often used to hide the default
- *  constructor <code>new</code>.
- *
- *     class SimpleSingleton  # Not thread safe
- *       private_class_method :new
- *       def SimpleSingleton.create(*args, &block)
- *         @me = new(*args, &block) if ! @me
- *         @me
- *       end
- *     end
- */
-
-static VALUE
-rb_mod_private_method(int argc, VALUE *argv, VALUE obj)
-{
-    set_method_visibility(CLASS_OF(obj), argc, argv, NOEX_PRIVATE);
-    return obj;
-}
-
-/*
- *  call-seq:
- *     public
- *     public(symbol, ...)
- *
- *  With no arguments, sets the default visibility for subsequently
- *  defined methods to public. With arguments, sets the named methods to
- *  have public visibility.
- */
-
-static VALUE
-top_public(int argc, VALUE *argv)
-{
-    return rb_mod_public(argc, argv, rb_cObject);
-}
-
-static VALUE
-top_private(int argc, VALUE *argv)
-{
-    return rb_mod_private(argc, argv, rb_cObject);
-}
-
-/*
- *  call-seq:
- *     module_function(symbol, ...)    => self
- *
- *  Creates module functions for the named methods. These functions may
- *  be called with the module as a receiver, and also become available
- *  as instance methods to classes that mix in the module. Module
- *  functions are copies of the original, and so may be changed
- *  independently. The instance-method versions are made private. If
- *  used with no arguments, subsequently defined methods become module
- *  functions.
- *
- *     module Mod
- *       def one
- *         "This is one"
- *       end
- *       module_function :one
- *     end
- *     class Cls
- *       include Mod
- *       def callOne
- *         one
- *       end
- *     end
- *     Mod.one     #=> "This is one"
- *     c = Cls.new
- *     c.callOne   #=> "This is one"
- *     module Mod
- *       def one
- *         "This is the new one"
- *       end
- *     end
- *     Mod.one     #=> "This is one"
- *     c.callOne   #=> "This is the new one"
- */
-
-static VALUE
-rb_mod_modfunc(int argc, VALUE *argv, VALUE module)
-{
-    int i;
-    ID id;
-    NODE *fbody;
-
-    if (TYPE(module) != T_MODULE) {
-	rb_raise(rb_eTypeError, "module_function must be called for modules");
-    }
-
-    secure_visibility(module);
-    if (argc == 0) {
-	SCOPE_SET(NOEX_MODFUNC);
-	return module;
-    }
-
-    set_method_visibility(module, argc, argv, NOEX_PRIVATE);
-
-    for (i = 0; i < argc; i++) {
-	VALUE m = module;
-
-	id = rb_to_id(argv[i]);
-	for (;;) {
-	    fbody = search_method(m, id, &m);
-	    if (fbody == 0) {
-		fbody = search_method(rb_cObject, id, &m);
-	    }
-	    if (fbody == 0 || fbody->nd_body == 0) {
-		rb_bug("undefined method `%s'; can't happen", rb_id2name(id));
-	    }
-	    if (nd_type(fbody->nd_body->nd_body) != NODE_ZSUPER) {
-		break;		/* normal case: need not to follow 'super' link */
-	    }
-	    m = RCLASS_SUPER(m);
-	    if (!m)
-		break;
-	}
-	rb_add_method(rb_singleton_class(module), id, fbody->nd_body->nd_body,
-		      NOEX_PUBLIC);
-    }
-    return module;
-}
-
-/*
- *  call-seq:
  *     append_features(mod)   => mod
  *
  *  When this module is included in another, Ruby calls
@@ -2409,7 +861,7 @@
 rb_obj_call_init(VALUE obj, int argc, VALUE *argv)
 {
     PASS_PASSED_BLOCK();
-    rb_funcall2(obj, init, argc, argv);
+    rb_funcall2(obj, idInitialize, argc, argv);
 }
 
 void
@@ -2530,12 +982,12 @@
     while (RUBY_VM_VALID_CONTROL_FRAME_P(cfp, end_cfp)) {
 	if (RUBY_VM_NORMAL_ISEQ_P(cfp->iseq)) {
 	    if (cfp->iseq->type == ISEQ_TYPE_RESCUE) {
-		return &cfp->dfp[-1];
+		return &cfp->dfp[-2];
 	    }
 	    else if (cfp->iseq->type == ISEQ_TYPE_ENSURE &&
-		     TYPE(cfp->dfp[-1]) != T_NODE &&
-		     !FIXNUM_P(cfp->dfp[-1])) {
-		return &cfp->dfp[-1];
+		     TYPE(cfp->dfp[-2]) != T_NODE &&
+		     !FIXNUM_P(cfp->dfp[-2])) {
+		return &cfp->dfp[-2];
 	    }
 	}
 	cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
@@ -2711,85 +1163,41 @@
     /* TODO: fix position */
     GET_THREAD()->vm->mark_object_ary = rb_ary_new();
 
-    init = rb_intern("initialize");
-    eqq = rb_intern("===");
-    each = rb_intern("each");
-
-    aref = rb_intern("[]");
-    aset = rb_intern("[]=");
-    match = rb_intern("=~");
-    missing = rb_intern("method_missing");
-    added = rb_intern("method_added");
-    singleton_added = rb_intern("singleton_method_added");
-    removed = rb_intern("method_removed");
-    singleton_removed = rb_intern("singleton_method_removed");
-    undefined = rb_intern("method_undefined");
-    singleton_undefined = rb_intern("singleton_method_undefined");
-
-    object_id = rb_intern("object_id");
-    __send__ = rb_intern("__send__");
-
     rb_define_virtual_variable("$@", errat_getter, errat_setter);
     rb_define_virtual_variable("$!", errinfo_getter, 0);
 
-    rb_define_private_method(rb_cBasicObject, "method_missing", rb_method_missing, -1);
-
     rb_define_global_function("eval", rb_f_eval, -1);
     rb_define_global_function("iterator?", rb_f_block_given_p, 0);
     rb_define_global_function("block_given?", rb_f_block_given_p, 0);
-    rb_define_global_function("loop", rb_f_loop, 0);
 
-    rb_define_method(rb_mKernel, "respond_to?", obj_respond_to, -1);
-    respond_to = rb_intern("respond_to?");
-    basic_respond_to = rb_method_node(rb_cObject, respond_to);
-    rb_register_mark_object((VALUE)basic_respond_to);
-
     rb_define_global_function("raise", rb_f_raise, -1);
     rb_define_global_function("fail", rb_f_raise, -1);
 
-    rb_define_global_function("caller", rb_f_caller, -1);
-
     rb_define_global_function("global_variables", rb_f_global_variables, 0);	/* in variable.c */
     rb_define_global_function("local_variables", rb_f_local_variables, 0);
 
     rb_define_global_function("__method__", rb_f_method_name, 0);
     rb_define_global_function("__callee__", rb_f_method_name, 0);
 
-    rb_define_method(rb_cBasicObject, "__send__", rb_f_send, -1);
-    rb_define_method(rb_mKernel, "send", rb_f_send, -1);
-    rb_define_method(rb_mKernel, "public_send", rb_f_public_send, -1);
-
-    rb_define_method(rb_cBasicObject, "instance_eval", rb_obj_instance_eval, -1);
-    rb_define_method(rb_cBasicObject, "instance_exec", rb_obj_instance_exec, -1);
-
     rb_define_private_method(rb_cModule, "append_features", rb_mod_append_features, 1);
     rb_define_private_method(rb_cModule, "extend_object", rb_mod_extend_object, 1);
     rb_define_private_method(rb_cModule, "include", rb_mod_include, -1);
-    rb_define_private_method(rb_cModule, "public", rb_mod_public, -1);
-    rb_define_private_method(rb_cModule, "protected", rb_mod_protected, -1);
-    rb_define_private_method(rb_cModule, "private", rb_mod_private, -1);
-    rb_define_private_method(rb_cModule, "module_function", rb_mod_modfunc, -1);
-    rb_define_method(rb_cModule, "method_defined?", rb_mod_method_defined, 1);
-    rb_define_method(rb_cModule, "public_method_defined?", rb_mod_public_method_defined, 1);
-    rb_define_method(rb_cModule, "private_method_defined?", rb_mod_private_method_defined, 1);
-    rb_define_method(rb_cModule, "protected_method_defined?", rb_mod_protected_method_defined, 1);
-    rb_define_method(rb_cModule, "public_class_method", rb_mod_public_method, -1);
-    rb_define_method(rb_cModule, "private_class_method", rb_mod_private_method, -1);
     rb_define_method(rb_cModule, "module_eval", rb_mod_module_eval, -1);
     rb_define_method(rb_cModule, "class_eval", rb_mod_module_eval, -1);
-    rb_define_method(rb_cModule, "module_exec", rb_mod_module_exec, -1);
-    rb_define_method(rb_cModule, "class_exec", rb_mod_module_exec, -1);
 
     rb_undef_method(rb_cClass, "module_function");
 
-    Init_eval_method();
+    {
+	extern void Init_vm_eval(void);
+	extern void Init_eval_method(void);
+	Init_vm_eval();
+	Init_eval_method();
+    }
 
     rb_define_singleton_method(rb_cModule, "nesting", rb_mod_nesting, 0);
     rb_define_singleton_method(rb_cModule, "constants", rb_mod_s_constants, -1);
 
     rb_define_singleton_method(rb_vm_top_self(), "include", top_include, -1);
-    rb_define_singleton_method(rb_vm_top_self(), "public", top_public, -1);
-    rb_define_singleton_method(rb_vm_top_self(), "private", top_private, -1);
 
     rb_define_method(rb_mKernel, "extend", rb_obj_extend, -1);
 
@@ -2853,3 +1261,5 @@
 {
     return GET_THREAD()->parse_in_eval != 0;
 }
+
+

Modified: MacRuby/branches/testing/eval_error.c
===================================================================
--- MacRuby/branches/testing/eval_error.c	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/eval_error.c	2008-06-05 08:33:02 UTC (rev 249)
@@ -3,34 +3,6 @@
  * included by eval.c
  */
 
-const char *
-rb_sourcefile(void)
-{
-    rb_thread_t *th = GET_THREAD();
-    rb_control_frame_t *cfp = vm_get_ruby_level_cfp(th, th->cfp);
-
-    if (cfp) {
-	return RSTRING_CPTR(cfp->iseq->filename);
-    }
-    else {
-	return 0;
-    }
-}
-
-int
-rb_sourceline(void)
-{
-    rb_thread_t *th = GET_THREAD();
-    rb_control_frame_t *cfp = vm_get_ruby_level_cfp(th, th->cfp);
-
-    if (cfp) {
-	return vm_get_sourceline(cfp);
-    }
-    else {
-	return 0;
-    }
-}
-
 static void
 warn_printf(const char *fmt, ...)
 {
@@ -79,6 +51,12 @@
     return rb_check_backtrace(info);
 }
 
+VALUE
+rb_get_backtrace(VALUE info)
+{
+    return get_backtrace(info);
+}
+
 static void
 set_backtrace(VALUE info, VALUE bt)
 {
@@ -210,7 +188,7 @@
 void
 rb_print_undef(VALUE klass, ID id, int scope)
 {
-    char *v;
+    const char *v;
 
     switch (scope) {
       default:
@@ -269,8 +247,7 @@
 	error_pos();
 	warn_printf(": unexpected throw\n");
 	break;
-      case TAG_RAISE:
-      case TAG_FATAL: {
+      case TAG_RAISE: {
 	VALUE errinfo = GET_THREAD()->errinfo;
 	if (rb_obj_is_kind_of(errinfo, rb_eSystemExit)) {
 	    status = sysexit_status(errinfo);
@@ -283,6 +260,9 @@
 	}
 	break;
       }
+      case TAG_FATAL:
+	error_print();
+	break;
       default:
 	rb_bug("Unknown longjmp status %d", ex);
 	break;

Modified: MacRuby/branches/testing/eval_intern.h
===================================================================
--- MacRuby/branches/testing/eval_intern.h	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/eval_intern.h	2008-06-05 08:33:02 UTC (rev 249)
@@ -183,17 +183,10 @@
 #define GET_THROWOBJ_CATCH_POINT(obj) ((VALUE*)RNODE((obj))->u2.value)
 #define GET_THROWOBJ_STATE(obj)       ((int)RNODE((obj))->u3.value)
 
-#define SCOPE_TEST(f) \
-  (ruby_cref()->nd_visi & (f))
+#define SCOPE_TEST(f)  (vm_cref()->nd_visi & (f))
+#define SCOPE_CHECK(f) (vm_cref()->nd_visi == (f))
+#define SCOPE_SET(f)   (vm_cref()->nd_visi = (f))
 
-#define SCOPE_CHECK(f) \
-  (ruby_cref()->nd_visi == (f))
-
-#define SCOPE_SET(f)  \
-{ \
-  ruby_cref()->nd_visi = (f); \
-}
-
 #define CHECK_STACK_OVERFLOW(cfp, margin) do \
   if (((VALUE *)(cfp)->sp) + (margin) + sizeof(rb_control_frame_t) >= ((VALUE *)cfp)) { \
       rb_exc_raise(sysstack_error); \
@@ -220,44 +213,17 @@
 
 NORETURN(void rb_fiber_start(void));
 
-NORETURN(void rb_raise_jump(VALUE));
 NORETURN(void rb_print_undef(VALUE, ID, int));
-NORETURN(void vm_localjump_error(const char *, VALUE, int));
+NORETURN(void vm_localjump_error(const char *,VALUE, int));
 NORETURN(void vm_jump_tag_but_local_jump(int, VALUE));
 
-NODE *vm_get_cref(rb_thread_t *th, rb_iseq_t *iseq, rb_control_frame_t *cfp);
-NODE *vm_cref_push(rb_thread_t *th, VALUE, int);
-NODE *vm_set_special_cref(rb_thread_t *th, VALUE *lfp, NODE * cref_stack);
 VALUE vm_make_jump_tag_but_local_jump(int state, VALUE val);
-
-static rb_control_frame_t *
-vm_get_ruby_level_cfp(rb_thread_t *th, rb_control_frame_t *cfp)
-{
-    while (!RUBY_VM_CONTROL_FRAME_STACK_OVERFLOW_P(th, cfp)) {
-	if (RUBY_VM_NORMAL_ISEQ_P(cfp->iseq)) {
-	    return cfp;
-	}
-	cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
-    }
-    return 0;
-}
-
-static inline NODE *
-ruby_cref()
-{
-    rb_thread_t *th = GET_THREAD();
-    rb_control_frame_t *cfp = vm_get_ruby_level_cfp(th, th->cfp);
-    return vm_get_cref(th, cfp->iseq, cfp);
-}
-
-VALUE vm_get_cbase(rb_thread_t *th);
+NODE *vm_cref(void);
+rb_control_frame_t *vm_get_ruby_level_cfp(rb_thread_t *th, rb_control_frame_t *cfp);
 VALUE rb_obj_is_proc(VALUE);
-void rb_vm_check_redefinition_opt_method(NODE *node);
-VALUE rb_vm_call_cfunc(VALUE recv, VALUE (*func)(VALUE), VALUE arg, rb_block_t *blockptr, VALUE filename);
+VALUE rb_vm_call_cfunc(VALUE recv, VALUE (*func)(VALUE), VALUE arg, const rb_block_t *blockptr, VALUE filename);
 void rb_thread_terminate_all(void);
-void rb_vm_set_eval_stack(rb_thread_t *, VALUE iseq);
 VALUE rb_vm_top_self();
+VALUE rb_vm_cbase(void);
 
-#define ruby_cbase() vm_get_cbase(GET_THREAD())
-
 #endif /* RUBY_EVAL_INTERN_H */

Modified: MacRuby/branches/testing/eval_jump.c
===================================================================
--- MacRuby/branches/testing/eval_jump.c	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/eval_jump.c	2008-06-05 08:33:02 UTC (rev 249)
@@ -5,162 +5,6 @@
 
 #include "eval_intern.h"
 
-NORETURN(static VALUE rb_f_throw _((int, VALUE *)));
-
-/*
- *  call-seq:
- *     throw(symbol [, obj])
- *
- *  Transfers control to the end of the active +catch+ block
- *  waiting for _symbol_. Raises +NameError+ if there
- *  is no +catch+ block for the symbol. The optional second
- *  parameter supplies a return value for the +catch+ block,
- *  which otherwise defaults to +nil+. For examples, see
- *  <code>Kernel::catch</code>.
- */
-
-static VALUE
-rb_f_throw(int argc, VALUE *argv)
-{
-    VALUE tag, value;
-    rb_thread_t *th = GET_THREAD();
-    struct rb_vm_tag *tt = th->tag;
-
-    rb_scan_args(argc, argv, "11", &tag, &value);
-    while (tt) {
-	if (tt->tag == tag) {
-	    tt->retval = value;
-	    break;
-	}
-	tt = tt->prev;
-    }
-    if (!tt) {
-	VALUE desc = rb_inspect(tag);
-	rb_raise(rb_eArgError, "uncaught throw %s", RSTRING_CPTR(desc));
-    }
-    rb_trap_restore_mask();
-    th->errinfo = NEW_THROW_OBJECT(tag, 0, TAG_THROW);
-
-    JUMP_TAG(TAG_THROW);
-#ifndef __GNUC__
-    return Qnil;		/* not reached */
-#endif
-}
-
-void
-rb_throw(const char *tag, VALUE val)
-{
-    VALUE argv[2];
-
-    argv[0] = ID2SYM(rb_intern(tag));
-    argv[1] = val;
-    rb_f_throw(2, argv);
-}
-
-void
-rb_throw_obj(VALUE tag, VALUE val)
-{
-    VALUE argv[2];
-
-    argv[0] = tag;
-    argv[1] = val;
-    rb_f_throw(2, argv);
-}
-
-/*
- *  call-seq:
- *     catch(symbol) {| | block }  > obj
- *
- *  +catch+ executes its block. If a +throw+ is
- *  executed, Ruby searches up its stack for a +catch+ block
- *  with a tag corresponding to the +throw+'s
- *  _symbol_. If found, that block is terminated, and
- *  +catch+ returns the value given to +throw+. If
- *  +throw+ is not called, the block terminates normally, and
- *  the value of +catch+ is the value of the last expression
- *  evaluated. +catch+ expressions may be nested, and the
- *  +throw+ call need not be in lexical scope.
- *
- *     def routine(n)
- *       puts n
- *       throw :done if n <= 0
- *       routine(n-1)
- *     end
- *
- *
- *     catch(:done) { routine(3) }
- *
- *  <em>produces:</em>
- *
- *     3
- *     2
- *     1
- *     0
- */
-
-static VALUE
-rb_f_catch(int argc, VALUE *argv)
-{
-    VALUE tag;
-    int state;
-    VALUE val = Qnil;		/* OK */
-    rb_thread_t *th = GET_THREAD();
-    rb_control_frame_t *saved_cfp = th->cfp;
-
-    if (argc == 0) {
-	tag = rb_obj_alloc(rb_cObject);
-    }
-    else {
-	rb_scan_args(argc, argv, "01", &tag);
-    }
-    PUSH_TAG();
-
-    th->tag->tag = tag;
-
-    if ((state = EXEC_TAG()) == 0) {
-	val = rb_yield_0(1, &tag);
-    }
-    else if (state == TAG_THROW && RNODE(th->errinfo)->u1.value == tag) {
-	th->cfp = saved_cfp;
-	val = th->tag->retval;
-	th->errinfo = Qnil;
-	state = 0;
-    }
-    POP_TAG();
-    if (state)
-	JUMP_TAG(state);
-
-    return val;
-}
-
-static VALUE
-catch_null_i(VALUE dmy)
-{
-    return rb_funcall(Qnil, rb_intern("catch"), 0, 0);
-}
-
-static VALUE
-catch_i(VALUE tag)
-{
-    return rb_funcall(Qnil, rb_intern("catch"), 1, tag);
-}
-
-VALUE
-rb_catch(const char *tag, VALUE (*func)(), VALUE data)
-{
-    if (!tag) {
-	return rb_iterate(catch_null_i, 0, func, data);
-    }
-    return rb_iterate(catch_i, ID2SYM(rb_intern(tag)), func, data);
-}
-
-VALUE
-rb_catch_obj(VALUE tag, VALUE (*func)(), VALUE data)
-{
-    return rb_iterate((VALUE (*)_((VALUE)))catch_i, tag, func, data);
-}
-
-
 /* exit */
 
 void
@@ -303,8 +147,6 @@
 void
 Init_jump(void)
 {
-    rb_define_global_function("catch", rb_f_catch, -1);
-    rb_define_global_function("throw", rb_f_throw, -1);
     rb_define_global_function("at_exit", rb_f_at_exit, 0);
     GC_ROOT(&end_procs);
 }

Deleted: MacRuby/branches/testing/eval_method.c
===================================================================
--- MacRuby/branches/testing/eval_method.c	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/eval_method.c	2008-06-05 08:33:02 UTC (rev 249)
@@ -1,700 +0,0 @@
-/* -*-c-*- */
-/*
- * This file is included by eval.c
- */
-
-#define CACHE_SIZE 0x800
-#define CACHE_MASK 0x7ff
-#define EXPR1(c,m) ((((c)>>3)^(m))&CACHE_MASK)
-
-struct cache_entry {		/* method hash table. */
-    ID mid;			/* method's id */
-    ID mid0;			/* method's original id */
-    VALUE klass;		/* receiver's class */
-    VALUE oklass;		/* original's class */
-    NODE *method;
-};
-
-static struct cache_entry cache[CACHE_SIZE];
-static int ruby_running = 0;
-
-void
-rb_clear_cache(void)
-{
-    struct cache_entry *ent, *end;
-
-    rb_vm_change_state();
-
-    if (!ruby_running)
-	return;
-    ent = cache;
-    end = ent + CACHE_SIZE;
-    while (ent < end) {
-	ent->mid = 0;
-	ent++;
-    }
-}
-
-static void
-rb_clear_cache_for_undef(VALUE klass, ID id)
-{
-    struct cache_entry *ent, *end;
-
-    rb_vm_change_state();
-
-    if (!ruby_running)
-	return;
-    ent = cache;
-    end = ent + CACHE_SIZE;
-    while (ent < end) {
-	if (ent->oklass == klass && ent->mid == id) {
-	    ent->mid = 0;
-	}
-	ent++;
-    }
-}
-
-static void
-rb_clear_cache_by_id(ID id)
-{
-    struct cache_entry *ent, *end;
-
-    rb_vm_change_state();
-
-    if (!ruby_running)
-	return;
-    ent = cache;
-    end = ent + CACHE_SIZE;
-    while (ent < end) {
-	if (ent->mid == id) {
-	    ent->mid = 0;
-	}
-	ent++;
-    }
-}
-
-void
-rb_clear_cache_by_class(VALUE klass)
-{
-    struct cache_entry *ent, *end;
-
-    rb_vm_change_state();
-
-    if (!ruby_running)
-	return;
-    ent = cache;
-    end = ent + CACHE_SIZE;
-    while (ent < end) {
-	if (ent->klass == klass || ent->oklass == klass) {
-	    ent->mid = 0;
-	}
-	ent++;
-    }
-}
-
-#if WITH_OBJC
-void rb_objc_sync_ruby_method(VALUE, ID, NODE*, unsigned);
-#endif
-
-void
-rb_add_method_direct(VALUE klass, ID mid, NODE *node)
-{
-    rb_clear_cache_by_id(mid);
-    st_insert(RCLASS_M_TBL(klass), (st_data_t)mid, (st_data_t)node);
-}
-
-void
-rb_add_method(VALUE klass, ID mid, NODE * node, int noex)
-{
-    NODE *body;
-
-    if (NIL_P(klass) || klass == 0) {
-	klass = rb_cObject;
-    }
-    if (rb_safe_level() >= 4 && (klass == rb_cObject || !OBJ_TAINTED(klass))) {
-	rb_raise(rb_eSecurityError, "Insecure: can't define method");
-    }
-    if (!FL_TEST(klass, FL_SINGLETON) &&
-	node && nd_type(node) != NODE_ZSUPER &&
-	(mid == rb_intern("initialize") || mid == rb_intern("initialize_copy"))) {
-	noex = NOEX_PRIVATE | noex;
-    }
-    else if (FL_TEST(klass, FL_SINGLETON) && node
-	     && nd_type(node) == NODE_CFUNC && mid == rb_intern("allocate")) {
-	rb_warn
-	    ("defining %s.allocate is deprecated; use rb_define_alloc_func()",
-	     rb_class2name(rb_iv_get(klass, "__attached__")));
-	mid = ID_ALLOCATOR;
-    }
-    if (OBJ_FROZEN(klass)) {
-	rb_error_frozen("class/module");
-    }
-    rb_clear_cache_by_id(mid);
-
-    /*
-     * NODE_METHOD (NEW_METHOD(body, klass, vis)):
-     *   nd_body : method body   // (2) // mark
-     *   nd_clss : klass         // (1) // mark
-     *   nd_noex : visibility    // (3)
-     *
-     * NODE_FBODY (NEW_FBODY(method, alias)):
-     *   nd_body : method (NODE_METHOD)  // (2) // mark
-     *   nd_oid  : original id           // (1)
-     *   nd_cnt  : alias count           // (3)
-     */
-    if (node) {
-	body = NEW_FBODY(NEW_METHOD(node, klass, NOEX_WITH_SAFE(noex)), 0);
-    }
-    else {
-	body = 0;
-    }
-
-    {
-	/* check re-definition */
-	st_data_t data;
-	NODE *old_node;
-
-	if (st_lookup(RCLASS_M_TBL(klass), mid, &data)) {
-	    old_node = (NODE *)data;
-	    if (old_node) {
-		if (nd_type(old_node->nd_body->nd_body) == NODE_CFUNC) {
-		    rb_vm_check_redefinition_opt_method(old_node);
-		}
-		if (RTEST(ruby_verbose) && node && old_node->nd_cnt == 0 && old_node->nd_body) {
-		    rb_warning("method redefined; discarding old %s", rb_id2name(mid));
-		}
-	    }
-	}
-	if (klass == rb_cObject && node && mid == init) {
-	    rb_warn("redefining Object#initialize may cause infinite loop");
-	}
-
-	if (mid == object_id || mid == __send__) {
-	    if (node && nd_type(node) == RUBY_VM_METHOD_NODE) {
-		rb_warn("redefining `%s' may cause serious problem",
-			rb_id2name(mid));
-	    }
-	}
-    }
-
-    st_insert(RCLASS_M_TBL(klass), mid, (st_data_t) body);
-
-#if WITH_OBJC
-    if (node != NULL && noex == NOEX_PUBLIC) {
-	unsigned override = !FL_TEST(klass, FL_SINGLETON);
-	rb_objc_sync_ruby_method(klass, mid, node, override);
-    }
-#endif
-
-    if (node && mid != ID_ALLOCATOR && ruby_running) {
-	if (FL_TEST(klass, FL_SINGLETON)) {
-	    rb_funcall(rb_iv_get(klass, "__attached__"), singleton_added, 1,
-		       ID2SYM(mid));
-	}
-	else {
-	    rb_funcall(klass, added, 1, ID2SYM(mid));
-	}
-    }
-}
-
-void
-rb_define_alloc_func(VALUE klass, VALUE (*func)(VALUE))
-{
-    Check_Type(klass, T_CLASS);
-    rb_add_method(rb_singleton_class(klass), ID_ALLOCATOR, NEW_CFUNC(func, 0),
-		  NOEX_PRIVATE);
-}
-
-void
-rb_undef_alloc_func(VALUE klass)
-{
-    Check_Type(klass, T_CLASS);
-    rb_add_method(rb_singleton_class(klass), ID_ALLOCATOR, 0, NOEX_UNDEF);
-}
-
-rb_alloc_func_t
-rb_get_alloc_func(VALUE klass)
-{
-    NODE *n;
-    Check_Type(klass, T_CLASS);
-    n = rb_method_node(CLASS_OF(klass), ID_ALLOCATOR);
-    if (!n) return 0;
-    if (nd_type(n) != NODE_METHOD) return 0;
-    n = n->nd_body;
-    if (nd_type(n) != NODE_CFUNC) return 0;
-    return (rb_alloc_func_t)n->nd_cfnc;
-}
-
-static NODE *
-search_method(VALUE klass, ID id, VALUE *klassp)
-{
-    st_data_t body;
-
-    if (!klass) {
-	return 0;
-    }
-
-    while (!st_lookup(RCLASS_M_TBL(klass), id, &body)) {
-	klass = RCLASS_SUPER(klass);
-	if (!klass)
-	    return 0;
-    }
-
-    if (klassp) {
-	*klassp = klass;
-    }
-
-    return (NODE *)body;
-}
-
-/*
- * search method body (NODE_METHOD)
- *   with    : klass and id
- *   without : method cache
- *
- * if you need method node with method cache, use
- * rb_method_node()
- */
-NODE *
-rb_get_method_body(VALUE klass, ID id, ID *idp)
-{
-    NODE *volatile fbody, *body;
-    NODE *method;
-
-    if ((fbody = search_method(klass, id, 0)) == 0 || !fbody->nd_body) {
-	/* store empty info in cache */
-	struct cache_entry *ent;
-	ent = cache + EXPR1(klass, id);
-	ent->klass = klass;
-	ent->mid = ent->mid0 = id;
-	ent->method = 0;
-	ent->oklass = 0;
-	return 0;
-    }
-
-    method = fbody->nd_body;
-
-    if (ruby_running) {
-	/* store in cache */
-	struct cache_entry *ent;
-	ent = cache + EXPR1(klass, id);
-	ent->klass = klass;
-	ent->mid = id;
-	ent->mid0 = fbody->nd_oid;
-	ent->method = body = method;
-	ent->oklass = method->nd_clss;
-    }
-    else {
-	body = method;
-    }
-
-    if (idp) {
-	*idp = fbody->nd_oid;
-    }
-
-    return body;
-}
-
-NODE *
-rb_method_node(VALUE klass, ID id)
-{
-    struct cache_entry *ent;
-
-    ent = cache + EXPR1(klass, id);
-    if (ent->mid == id && ent->klass == klass && ent->method) {
-	return ent->method;
-    }
-
-    return rb_get_method_body(klass, id, 0);
-}
-
-static void
-remove_method(VALUE klass, ID mid)
-{
-    st_data_t data;
-    NODE *body = 0;
-
-    if (klass == rb_cObject) {
-	rb_secure(4);
-    }
-    if (rb_safe_level() >= 4 && !OBJ_TAINTED(klass)) {
-	rb_raise(rb_eSecurityError, "Insecure: can't remove method");
-    }
-    if (OBJ_FROZEN(klass))
-	rb_error_frozen("class/module");
-    if (mid == object_id || mid == __send__ || mid == init) {
-	rb_warn("removing `%s' may cause serious problem", rb_id2name(mid));
-    }
-    if (st_lookup(RCLASS_M_TBL(klass), mid, &data)) {
-	body = (NODE *)data;
-	if (!body || !body->nd_body) body = 0;
-	else {
-	    st_delete(RCLASS_M_TBL(klass), &mid, &data);
-	}
-    }
-    if (!body) {
-	rb_name_error(mid, "method `%s' not defined in %s",
-		      rb_id2name(mid), rb_class2name(klass));
-    }
-
-    if (nd_type(body->nd_body->nd_body) == NODE_CFUNC) {
-	rb_vm_check_redefinition_opt_method(body);
-    }
-
-    rb_clear_cache_for_undef(klass, mid);
-    if (FL_TEST(klass, FL_SINGLETON)) {
-	rb_funcall(rb_iv_get(klass, "__attached__"), singleton_removed, 1,
-		   ID2SYM(mid));
-    }
-    else {
-	rb_funcall(klass, removed, 1, ID2SYM(mid));
-    }
-}
-
-void
-rb_remove_method(VALUE klass, const char *name)
-{
-    remove_method(klass, rb_intern(name));
-}
-
-/*
- *  call-seq:
- *     remove_method(symbol)   => self
- *
- *  Removes the method identified by _symbol_ from the current
- *  class. For an example, see <code>Module.undef_method</code>.
- */
-
-static VALUE
-rb_mod_remove_method(int argc, VALUE *argv, VALUE mod)
-{
-    int i;
-
-    for (i = 0; i < argc; i++) {
-	remove_method(mod, rb_to_id(argv[i]));
-    }
-    return mod;
-}
-
-#undef rb_disable_super
-#undef rb_enable_super
-
-void
-rb_disable_super(VALUE klass, const char *name)
-{
-    /* obsolete - no use */
-}
-
-void
-rb_enable_super(VALUE klass, const char *name)
-{
-    rb_warning("rb_enable_super() is obsolete");
-}
-
-static void
-rb_export_method(VALUE klass, ID name, ID noex)
-{
-    NODE *fbody;
-    VALUE origin;
-
-    if (klass == rb_cObject) {
-	rb_secure(4);
-    }
-    fbody = search_method(klass, name, &origin);
-    if (!fbody && TYPE(klass) == T_MODULE) {
-	fbody = search_method(rb_cObject, name, &origin);
-    }
-    if (!fbody || !fbody->nd_body) {
-	rb_print_undef(klass, name, 0);
-    }
-    if (fbody->nd_body->nd_noex != noex) {
-	if (nd_type(fbody->nd_body->nd_body) == NODE_CFUNC) {
-	    rb_vm_check_redefinition_opt_method(fbody);
-	}
-	if (klass == origin) {
-	    fbody->nd_body->nd_noex = noex;
-	}
-	else {
-	    rb_add_method(klass, name, NEW_ZSUPER(), noex);
-	}
-    }
-}
-
-int
-rb_method_boundp(VALUE klass, ID id, int ex)
-{
-    NODE *method;
-
-    if ((method = rb_method_node(klass, id)) != 0) {
-	if (ex && (method->nd_noex & NOEX_PRIVATE)) {
-	    return Qfalse;
-	}
-	return Qtrue;
-    }
-    return Qfalse;
-}
-
-void
-rb_attr(VALUE klass, ID id, int read, int write, int ex)
-{
-    const char *name;
-    ID attriv;
-    int noex;
-
-    if (!ex) {
-	noex = NOEX_PUBLIC;
-    }
-    else {
-	if (SCOPE_TEST(NOEX_PRIVATE)) {
-	    noex = NOEX_PRIVATE;
-	    rb_warning((SCOPE_CHECK(NOEX_MODFUNC)) ?
-		       "attribute accessor as module_function" :
-		       "private attribute?");
-	}
-	else if (SCOPE_TEST(NOEX_PROTECTED)) {
-	    noex = NOEX_PROTECTED;
-	}
-	else {
-	    noex = NOEX_PUBLIC;
-	}
-    }
-
-    if (!rb_is_local_id(id) && !rb_is_const_id(id)) {
-	rb_name_error(id, "invalid attribute name `%s'", rb_id2name(id));
-    }
-    name = rb_id2name(id);
-    if (!name) {
-	rb_raise(rb_eArgError, "argument needs to be symbol or string");
-    }
-    attriv = rb_intern_str(rb_sprintf("@%s", name));
-    if (read) {
-	rb_add_method(klass, id, NEW_IVAR(attriv), noex);
-    }
-    if (write) {
-	rb_add_method(klass, rb_id_attrset(id), NEW_ATTRSET(attriv), noex);
-    }
-}
-
-void
-rb_undef(VALUE klass, ID id)
-{
-    VALUE origin;
-    NODE *body;
-
-    if (ruby_cbase() == rb_cObject && klass == rb_cObject) {
-	rb_secure(4);
-    }
-    if (rb_safe_level() >= 4 && !OBJ_TAINTED(klass)) {
-	rb_raise(rb_eSecurityError, "Insecure: can't undef `%s'",
-		 rb_id2name(id));
-    }
-    rb_frozen_class_p(klass);
-    if (id == object_id || id == __send__ || id == init) {
-	rb_warn("undefining `%s' may cause serious problem", rb_id2name(id));
-    }
-#if WITH_OBJC
-    /* TODO: we should only warn regarding important NSObject methods that
-       are necessary by the GC to call finalizers. */
-    if (class_respondsToSelector(RCLASS_OCID(rb_cBasicObject),
-				 sel_registerName(rb_id2name(id)))) {
-	rb_warn("undefining `NSObject#%s' may cause serious problem", 
-		rb_id2name(id));
-    }
-#endif
-    body = search_method(klass, id, &origin);
-    if (!body || !body->nd_body) {
-	char *s0 = " class";
-	VALUE c = klass;
-
-	if (FL_TEST(c, FL_SINGLETON)) {
-	    VALUE obj = rb_iv_get(klass, "__attached__");
-
-	    switch (TYPE(obj)) {
-	      case T_MODULE:
-	      case T_CLASS:
-		c = obj;
-		s0 = "";
-	    }
-	}
-	else if (TYPE(c) == T_MODULE) {
-	    s0 = " module";
-	}
-#if WITH_OBJC
-	if (!class_respondsToSelector(RCLASS(klass)->ocklass,
-	    			      sel_registerName(rb_id2name(id))))
-#endif
-	rb_name_error(id, "undefined method `%s' for%s `%s'",
-		      rb_id2name(id), s0, rb_class2name(c));
-    }
-
-    rb_add_method(klass, id, 0, NOEX_PUBLIC);
-
-#if WITH_OBJC
-    {
-	Method method;
-        method = class_getInstanceMethod(RCLASS(klass)->ocklass,
-	 				 sel_registerName(rb_id2name(id)));
-	if (method != NULL)
-	    method_setImplementation(method, NULL);
-    }
-#endif
-
-    if (FL_TEST(klass, FL_SINGLETON)) {
-	rb_funcall(rb_iv_get(klass, "__attached__"),
-		   singleton_undefined, 1, ID2SYM(id));
-    }
-    else {
-	rb_funcall(klass, undefined, 1, ID2SYM(id));
-    }
-}
-
-/*
- *  call-seq:
- *     undef_method(symbol)    => self
- *
- *  Prevents the current class from responding to calls to the named
- *  method. Contrast this with <code>remove_method</code>, which deletes
- *  the method from the particular class; Ruby will still search
- *  superclasses and mixed-in modules for a possible receiver.
- *
- *     class Parent
- *       def hello
- *         puts "In parent"
- *       end
- *     end
- *     class Child < Parent
- *       def hello
- *         puts "In child"
- *       end
- *     end
- *
- *
- *     c = Child.new
- *     c.hello
- *
- *
- *     class Child
- *       remove_method :hello  # remove from child, still in parent
- *     end
- *     c.hello
- *
- *
- *     class Child
- *       undef_method :hello   # prevent any calls to 'hello'
- *     end
- *     c.hello
- *
- *  <em>produces:</em>
- *
- *     In child
- *     In parent
- *     prog.rb:23: undefined method `hello' for #<Child:0x401b3bb4> (NoMethodError)
- */
-
-static VALUE
-rb_mod_undef_method(int argc, VALUE *argv, VALUE mod)
-{
-    int i;
-    for (i = 0; i < argc; i++) {
-	rb_undef(mod, rb_to_id(argv[i]));
-    }
-    return mod;
-}
-
-void
-rb_alias(VALUE klass, ID name, ID def)
-{
-    NODE *orig_fbody, *node;
-    VALUE singleton = 0;
-    st_data_t data;
-
-    rb_frozen_class_p(klass);
-    if (klass == rb_cObject) {
-	rb_secure(4);
-    }
-    orig_fbody = search_method(klass, def, 0);
-    if (!orig_fbody || !orig_fbody->nd_body) {
-	if (TYPE(klass) == T_MODULE) {
-	    orig_fbody = search_method(rb_cObject, def, 0);
-	}
-    }
-    if (!orig_fbody || !orig_fbody->nd_body) {
-	rb_print_undef(klass, def, 0);
-    }
-    if (FL_TEST(klass, FL_SINGLETON)) {
-	singleton = rb_iv_get(klass, "__attached__");
-    }
-
-    orig_fbody->nd_cnt++;
-
-    if (st_lookup(RCLASS_M_TBL(klass), name, &data)) {
-	node = (NODE *)data;
-	if (node) {
-	    if (RTEST(ruby_verbose) && node->nd_cnt == 0 && node->nd_body) {
-		rb_warning("discarding old %s", rb_id2name(name));
-	    }
-	    if (nd_type(node->nd_body->nd_body) == NODE_CFUNC) {
-		rb_vm_check_redefinition_opt_method(node);
-	    }
-	}
-    }
-
-    st_insert(RCLASS_M_TBL(klass), name,
-	      (st_data_t) NEW_FBODY(
-		  NEW_METHOD(orig_fbody->nd_body->nd_body,
-			     orig_fbody->nd_body->nd_clss,
-			     NOEX_WITH_SAFE(orig_fbody->nd_body->nd_noex)), def));
-
-#if WITH_OBJC
-    if (orig_fbody->nd_body->nd_noex == NOEX_PUBLIC)
-	rb_objc_sync_ruby_method(klass, name, orig_fbody->nd_body->nd_body, 0);
-#endif
-
-    rb_clear_cache_by_id(name);
-
-    if (!ruby_running) return;
-
-    if (singleton) {
-	rb_funcall(singleton, singleton_added, 1, ID2SYM(name));
-    }
-    else {
-	rb_funcall(klass, added, 1, ID2SYM(name));
-    }
-}
-
-/*
- *  call-seq:
- *     alias_method(new_name, old_name)   => self
- *
- *  Makes <i>new_name</i> a new copy of the method <i>old_name</i>. This can
- *  be used to retain access to methods that are overridden.
- *
- *     module Mod
- *       alias_method :orig_exit, :exit
- *       def exit(code=0)
- *         puts "Exiting with code #{code}"
- *         orig_exit(code)
- *       end
- *     end
- *     include Mod
- *     exit(99)
- *
- *  <em>produces:</em>
- *
- *     Exiting with code 99
- */
-
-static VALUE
-rb_mod_alias_method(VALUE mod, VALUE newname, VALUE oldname)
-{
-    rb_alias(mod, rb_to_id(newname), rb_to_id(oldname));
-    return mod;
-}
-
-static void
-Init_eval_method(void)
-{
-    rb_define_private_method(rb_cModule, "remove_method", rb_mod_remove_method, -1);
-    rb_define_private_method(rb_cModule, "undef_method", rb_mod_undef_method, -1);
-    rb_define_private_method(rb_cModule, "alias_method", rb_mod_alias_method, 2);
-}

Modified: MacRuby/branches/testing/ext/nkf/nkf-utf8/nkf.c
===================================================================
--- MacRuby/branches/testing/ext/nkf/nkf-utf8/nkf.c	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/ext/nkf/nkf-utf8/nkf.c	2008-06-05 08:33:02 UTC (rev 249)
@@ -1,39 +1,39 @@
 /** Network Kanji Filter. (PDS Version)
-** -*- coding: ISO-2022-JP -*-
-************************************************************************
-** Copyright (C) 1987, Fujitsu LTD. (Itaru ICHIKAWA)
-** $BO"Mm at h!'(B $B!J3t!KIY;NDL8&5f=j!!%=%U%H#38&!!;T at n!!;j(B
-** $B!J(BE-Mail Address: ichikawa at flab.fujitsu.co.jp$B!K(B
-** Copyright (C) 1996,1998
-** Copyright (C) 2002
-** $BO"Mm at h!'(B $BN05eBg3X>pJs9)3X2J(B $B2OLn(B $B??<#(B  mime/X0208 support
-** $B!J(BE-Mail Address: kono at ie.u-ryukyu.ac.jp$B!K(B
-** $BO"Mm at h!'(B COW for DOS & Win16 & Win32 & OS/2
-** $B!J(BE-Mail Address: GHG00637 at niftyserve.or.p$B!K(B
-**
-**    $B$3$N%=!<%9$N$$$+$J$kJ#<L!$2~JQ!$=$@5$b5vBz$7$^$9!#$?$@$7!"(B
-**    $B$=$N:]$K$O!"C/$,9W8%$7$?$r<($9$3$NItJ,$r;D$9$3$H!#(B
-**    $B:FG[I[$d;(;o$NIUO?$J$I$NLd$$9g$o$;$bI,MW$"$j$^$;$s!#(B
-**    $B1DMxMxMQ$b>e5-$KH?$7$J$$HO0O$G5v2D$7$^$9!#(B
-**    $B%P%$%J%j$NG[I[$N:]$K$O(Bversion message$B$rJ]B8$9$k$3$H$r>r7o$H$7$^$9!#(B
-**    $B$3$N%W%m%0%i%`$K$D$$$F$OFC$K2?$NJ]>Z$b$7$J$$!"0-$7$+$i$:!#(B
-**
-**    Everyone is permitted to do anything on this program
-**    including copying, modifying, improving,
-**    as long as you don't try to pretend that you wrote it.
-**    i.e., the above copyright notice has to appear in all copies.
-**    Binary distribution requires original version messages.
-**    You don't have to ask before copying, redistribution or publishing.
-**    THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE.
-***********************************************************************/
+ ** -*- coding: ISO-2022-JP -*-
+ ************************************************************************
+ ** Copyright (C) 1987, Fujitsu LTD. (Itaru ICHIKAWA)
+ ** $BO"Mm at h!'(B $B!J3t!KIY;NDL8&5f=j!!%=%U%H#38&!!;T at n!!;j(B
+ ** $B!J(BE-Mail Address: ichikawa at flab.fujitsu.co.jp$B!K(B
+ ** Copyright (C) 1996,1998
+ ** Copyright (C) 2002
+ ** $BO"Mm at h!'(B $BN05eBg3X>pJs9)3X2J(B $B2OLn(B $B??<#(B  mime/X0208 support
+ ** $B!J(BE-Mail Address: kono at ie.u-ryukyu.ac.jp$B!K(B
+ ** $BO"Mm at h!'(B COW for DOS & Win16 & Win32 & OS/2
+ ** $B!J(BE-Mail Address: GHG00637 at niftyserve.or.p$B!K(B
+ **
+ **    $B$3$N%=!<%9$N$$$+$J$kJ#<L!$2~JQ!$=$@5$b5vBz$7$^$9!#$?$@$7!"(B
+ **    $B$=$N:]$K$O!"C/$,9W8%$7$?$r<($9$3$NItJ,$r;D$9$3$H!#(B
+ **    $B:FG[I[$d;(;o$NIUO?$J$I$NLd$$9g$o$;$bI,MW$"$j$^$;$s!#(B
+ **    $B1DMxMxMQ$b>e5-$KH?$7$J$$HO0O$G5v2D$7$^$9!#(B
+ **    $B%P%$%J%j$NG[I[$N:]$K$O(Bversion message$B$rJ]B8$9$k$3$H$r>r7o$H$7$^$9!#(B
+ **    $B$3$N%W%m%0%i%`$K$D$$$F$OFC$K2?$NJ]>Z$b$7$J$$!"0-$7$+$i$:!#(B
+ **
+ **    Everyone is permitted to do anything on this program
+ **    including copying, modifying, improving,
+ **    as long as you don't try to pretend that you wrote it.
+ **    i.e., the above copyright notice has to appear in all copies.
+ **    Binary distribution requires original version messages.
+ **    You don't have to ask before copying, redistribution or publishing.
+ **    THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE.
+ ***********************************************************************/
 
 /***********************************************************************
  * $B8=:_!"(Bnkf $B$O(B SorceForge $B$K$F%a%s%F%J%s%9$,B3$1$i$l$F$$$^$9!#(B
  * http://sourceforge.jp/projects/nkf/
-***********************************************************************/
-#define NKF_IDENT "$Id: nkf.c 16149 2008-04-22 12:20:36Z naruse $"
+ ***********************************************************************/
+#define NKF_IDENT "$Id: nkf.c 16515 2008-05-21 21:23:51Z naruse $"
 #define NKF_VERSION "2.0.8"
-#define NKF_RELEASE_DATE "2008-01-23"
+#define NKF_RELEASE_DATE "2008-02-08"
 #define COPY_RIGHT \
     "Copyright (C) 1987, FUJITSU LTD. (I.Ichikawa),2000 S. Kono, COW\n" \
     "Copyright (C) 2002-2008 Kono, Furukawa, Naruse, mastodon"
@@ -45,10 +45,10 @@
 /* state of output_mode and input_mode
 
    c2           0 means ASCII
-                JIS_X_0201
-                ISO_8859_1
-                JIS_X_0208
-                EOF      all termination
+   JIS_X_0201_1976_K
+   ISO_8859_1
+   JIS_X_0208
+   EOF      all termination
    c1           32bit data
 
  */
@@ -74,12 +74,10 @@
 #define         CR      0x0d
 #define         ESC     0x1b
 #define         SP      0x20
-#define         AT      0x40
-#define         SSP     0xa0
 #define         DEL     0x7f
 #define         SI      0x0f
 #define         SO      0x0e
-#define         SSO     0x8e
+#define         SS2     0x8e
 #define         SS3     0x8f
 #define         CRLF    0x0D0A
 
@@ -95,10 +93,12 @@
     CP50222,
     ISO_2022_JP_1,
     ISO_2022_JP_3,
+    ISO_2022_JP_2004,
     SHIFT_JIS,
     WINDOWS_31J,
     CP10001,
     EUC_JP,
+    EUCJP_NKF,
     CP51932,
     EUCJP_MS,
     EUCJP_ASCII,
@@ -120,26 +120,30 @@
     UTF_32BE_BOM,
     UTF_32LE,
     UTF_32LE_BOM,
+    BINARY,
     NKF_ENCODING_TABLE_SIZE,
-    JIS_X_0201=0x1000,
-    JIS_X_0208=0x1001,
-    JIS_X_0212=0x1002,
-    JIS_X_0213_1=0x1003,
-    JIS_X_0213_2=0x1004,
-    BINARY
+    JIS_X_0201_1976_K = 0x1013, /* I */ /* JIS C 6220-1969 */
+    /* JIS_X_0201_1976_R = 0x1014, */ /* J */ /* JIS C 6220-1969 */
+    /* JIS_X_0208_1978   = 0x1040, */ /* @ */ /* JIS C 6226-1978 */
+    /* JIS_X_0208_1983   = 0x1087, */ /* B */ /* JIS C 6226-1983 */
+    JIS_X_0208        = 0x1168, /* @B */
+    JIS_X_0212        = 0x1159, /* D */
+    /* JIS_X_0213_2000_1 = 0x1228, */ /* O */
+    JIS_X_0213_2 = 0x1229, /* P */
+    JIS_X_0213_1 = 0x1233, /* Q */
 };
 
-nkf_char s_iconv(nkf_char c2, nkf_char c1, nkf_char c0);
-nkf_char e_iconv(nkf_char c2, nkf_char c1, nkf_char c0);
-nkf_char w_iconv(nkf_char c2, nkf_char c1, nkf_char c0);
-nkf_char w_iconv16(nkf_char c2, nkf_char c1, nkf_char c0);
-nkf_char w_iconv32(nkf_char c2, nkf_char c1, nkf_char c0);
-void j_oconv(nkf_char c2, nkf_char c1);
-void s_oconv(nkf_char c2, nkf_char c1);
-void e_oconv(nkf_char c2, nkf_char c1);
-void w_oconv(nkf_char c2, nkf_char c1);
-void w_oconv16(nkf_char c2, nkf_char c1);
-void w_oconv32(nkf_char c2, nkf_char c1);
+static nkf_char s_iconv(nkf_char c2, nkf_char c1, nkf_char c0);
+static nkf_char e_iconv(nkf_char c2, nkf_char c1, nkf_char c0);
+static nkf_char w_iconv(nkf_char c2, nkf_char c1, nkf_char c0);
+static nkf_char w_iconv16(nkf_char c2, nkf_char c1, nkf_char c0);
+static nkf_char w_iconv32(nkf_char c2, nkf_char c1, nkf_char c0);
+static void j_oconv(nkf_char c2, nkf_char c1);
+static void s_oconv(nkf_char c2, nkf_char c1);
+static void e_oconv(nkf_char c2, nkf_char c1);
+static void w_oconv(nkf_char c2, nkf_char c1);
+static void w_oconv16(nkf_char c2, nkf_char c1);
+static void w_oconv32(nkf_char c2, nkf_char c1);
 
 typedef struct {
     const char *name;
@@ -170,10 +174,12 @@
     {CP50222,		"CP50222",		&NkfEncodingISO_2022_JP},
     {ISO_2022_JP_1,	"ISO-2022-JP-1",	&NkfEncodingISO_2022_JP},
     {ISO_2022_JP_3,	"ISO-2022-JP-3",	&NkfEncodingISO_2022_JP},
+    {ISO_2022_JP_2004,	"ISO-2022-JP-2004",	&NkfEncodingISO_2022_JP},
     {SHIFT_JIS,		"Shift_JIS",		&NkfEncodingShift_JIS},
     {WINDOWS_31J,	"Windows-31J",		&NkfEncodingShift_JIS},
     {CP10001,		"CP10001",		&NkfEncodingShift_JIS},
     {EUC_JP,		"EUC-JP",		&NkfEncodingEUC_JP},
+    {EUCJP_NKF,		"eucJP-nkf",		&NkfEncodingEUC_JP},
     {CP51932,		"CP51932",		&NkfEncodingEUC_JP},
     {EUCJP_MS,		"eucJP-MS",		&NkfEncodingEUC_JP},
     {EUCJP_ASCII,	"eucJP-ASCII",		&NkfEncodingEUC_JP},
@@ -209,9 +215,11 @@
     {"ISO2022JP-CP932",		CP50220},
     {"CP50220",			CP50220},
     {"CP50221",			CP50221},
+    {"CSISO2022JP",		CP50221},
     {"CP50222",			CP50222},
     {"ISO-2022-JP-1",		ISO_2022_JP_1},
     {"ISO-2022-JP-3",		ISO_2022_JP_3},
+    {"ISO-2022-JP-2004",	ISO_2022_JP_2004},
     {"SHIFT_JIS",		SHIFT_JIS},
     {"SJIS",			SHIFT_JIS},
     {"WINDOWS-31J",		WINDOWS_31J},
@@ -221,6 +229,7 @@
     {"CP10001",			CP10001},
     {"EUCJP",			EUC_JP},
     {"EUC-JP",			EUC_JP},
+    {"EUCJP-NKF",		EUCJP_NKF},
     {"CP51932",			CP51932},
     {"EUC-JP-MS",		EUCJP_MS},
     {"EUCJP-MS",		EUCJP_MS},
@@ -258,13 +267,11 @@
 #define	    DEFAULT_ENCIDX EUC_JP
 #elif defined(DEFAULT_CODE_UTF8)
 #define	    DEFAULT_ENCIDX UTF_8
-#else
-#define	    DEFAULT_ENCIDX 0
 #endif
 
 
 #define		is_alnum(c)  \
-            (('a'<=c && c<='z')||('A'<= c && c<='Z')||('0'<=c && c<='9'))
+    (('a'<=c && c<='z')||('A'<= c && c<='Z')||('0'<=c && c<='9'))
 
 /* I don't trust portablity of toupper */
 #define nkf_toupper(c)  (('a'<=c && c<='z')?(c-('a'-'A')):c)
@@ -278,15 +285,16 @@
 #define nkf_isprint(c) (SP<=c && c<='~')
 #define nkf_isgraph(c) ('!'<=c && c<='~')
 #define hex2bin(c) (('0'<=c&&c<='9') ? (c-'0') : \
-                    ('A'<=c&&c<='F') ? (c-'A'+10) : \
-                    ('a'<=c&&c<='f') ? (c-'a'+10) : 0)
+		    ('A'<=c&&c<='F') ? (c-'A'+10) : \
+		    ('a'<=c&&c<='f') ? (c-'a'+10) : 0)
 #define bin2hex(c) ("0123456789ABCDEF"[c&15])
 #define is_eucg3(c2) (((unsigned short)c2 >> 8) == SS3)
 #define nkf_noescape_mime(c) ((c == CR) || (c == LF) || \
-    ((c > SP) && (c < DEL) && (c != '?') && (c != '=') && (c != '_') \
-     && (c != '(') && (c != ')') && (c != '.') && (c != 0x22)))
+			      ((c > SP) && (c < DEL) && (c != '?') && (c != '=') && (c != '_') \
+			       && (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         HOLD_SIZE       1024
 #if defined(INT_IS_SHORT)
@@ -324,8 +332,7 @@
 static nkf_encoding *input_encoding = NULL;
 static nkf_encoding *output_encoding = NULL;
 
-static  nkf_char     kanji_convert(FILE *f);
-static  nkf_char     h_conv(FILE *f,nkf_char c2,nkf_char c1);
+static int kanji_convert(FILE *f);
 #if defined(UTF8_INPUT_ENABLE) || defined(UTF8_OUTPUT_ENABLE)
 /* UCS Mapping
  * 0: Shift_JIS, eucJP-ascii
@@ -353,12 +360,6 @@
 static  int     output_bom_f = FALSE;
 static  int     output_endian = ENDIAN_BIG;
 #endif
-static  void    fold_conv(nkf_char c2,nkf_char c1);
-static  void    eol_conv(nkf_char c2,nkf_char c1);
-static  void    z_conv(nkf_char c2,nkf_char c1);
-static  void    rot_conv(nkf_char c2,nkf_char c1);
-static  void    hira_conv(nkf_char c2,nkf_char c1);
-static  void    iso2022jp_check_conv(nkf_char c2,nkf_char c1);
 
 static  void    std_putc(nkf_char c);
 static  nkf_char     std_getc(FILE *f);
@@ -411,13 +412,17 @@
 static nkf_char (*i_uungetc)(nkf_char c ,FILE *f) = std_ungetc;
 #endif
 
-#define PREFIX_EUCG3	NKF_INT32_C(0x8F00)
-#define CLASS_MASK	NKF_INT32_C(0xFF000000)
-#define CLASS_UNICODE	NKF_INT32_C(0x01000000)
-#define VALUE_MASK	NKF_INT32_C(0x00FFFFFF)
-#define UNICODE_MAX	NKF_INT32_C(0x0010FFFF)
-#define is_unicode_capsule(c) ((c & CLASS_MASK) == CLASS_UNICODE)
-#define is_unicode_bmp(c) ((c & VALUE_MASK) <= NKF_INT32_C(0xFFFF))
+#define PREFIX_EUCG3    NKF_INT32_C(0x8F00)
+#define CLASS_MASK      NKF_INT32_C(0xFF000000)
+#define CLASS_UNICODE   NKF_INT32_C(0x01000000)
+#define VALUE_MASK      NKF_INT32_C(0x00FFFFFF)
+#define UNICODE_BMP_MAX NKF_INT32_C(0x0000FFFF)
+#define UNICODE_MAX     NKF_INT32_C(0x0010FFFF)
+#define nkf_char_euc3_new(c) ((c) | PREFIX_EUCG3)
+#define nkf_char_unicode_new(c) ((c) | CLASS_UNICODE)
+#define nkf_char_unicode_p(c) ((c & CLASS_MASK) == CLASS_UNICODE)
+#define nkf_char_unicode_bmp_p(c) ((c & VALUE_MASK) <= NKF_INT32_C(UNICODE_BMP_MAX))
+#define nkf_char_unicode_value_p(c) ((c & VALUE_MASK) <= NKF_INT32_C(UNICODE_MAX))
 
 #ifdef NUMCHAR_OPTION
 static int numchar_f = FALSE;
@@ -450,9 +455,7 @@
 /* static nkf_char cp932_conv(nkf_char c2, nkf_char c1); */
 #endif /* SHIFTJIS_CP932 */
 
-#ifdef X0212_ENABLE
 static int x0212_f = FALSE;
-#endif
 static int x0213_f = FALSE;
 
 static unsigned char prefix_table[256];
@@ -465,8 +468,6 @@
     {"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}
 };
@@ -496,14 +497,16 @@
 
 /* process default */
 
-nkf_char no_connection2(nkf_char c2, nkf_char c1, nkf_char c0)
+static nkf_char
+no_connection2(nkf_char c2, nkf_char c1, nkf_char c0)
 {
     fprintf(stderr,"nkf internal module connection failure.\n");
     exit(1);
     return 0; /* LINT */
 }
 
-void no_connection(nkf_char c2, nkf_char c1)
+static void
+no_connection(nkf_char c2, nkf_char c1)
 {
     no_connection2(c2,c1,0);
 }
@@ -539,9 +542,8 @@
 static  nkf_char    (*i_mungetc_buf)(nkf_char c,FILE *f) = std_ungetc;
 
 /* Global states */
-static int output_mode = ASCII,    /* output kanji mode */
-           input_mode =  ASCII,    /* input kanji mode */
-           shift_mode =  FALSE;    /* TRUE shift out, or X0201  */
+static int output_mode = ASCII;    /* output kanji mode */
+static int input_mode =  ASCII;    /* input kanji mode */
 static int mime_decode_mode =   FALSE;    /* MIME mode B base64, Q hex */
 
 /* X0201 / X0208 conversion tables */
@@ -651,49 +653,41 @@
 nkf_char std_gc_buf[STD_GC_BUFSIZE];
 nkf_char std_gc_ndx;
 
-char* nkf_strcpy(const char *str)
+static int
+nkf_str_caseeql(const char *src, const char *target)
 {
-    char* result = malloc(strlen(str) + 1);
-    if (!result){
-	perror(str);
-	return "";
+    int i;
+    for (i = 0; src[i] && target[i]; i++) {
+	if (nkf_toupper(src[i]) != nkf_toupper(target[i])) return FALSE;
     }
-    strcpy(result, str);
-    return result;
+    if (src[i] || target[i]) return FALSE;
+    else return TRUE;
 }
 
-static void nkf_str_upcase(const char *src, char *dest, size_t length)
+static nkf_encoding*
+nkf_enc_from_index(int idx)
 {
-    int i = 0;
-    for (; i < length && src[i]; i++) {
-	dest[i] = nkf_toupper(src[i]);
-    }
-    dest[i] = 0;
-}
-
-static nkf_encoding *nkf_enc_from_index(int idx)
-{
     if (idx < 0 || NKF_ENCODING_TABLE_SIZE <= idx) {
-	if (idx == BINARY)
-	    return &nkf_encoding_table[NKF_ENCODING_TABLE_SIZE];
 	return 0;
     }
     return &nkf_encoding_table[idx];
 }
 
-static int nkf_enc_find_index(const char *name)
+static int
+nkf_enc_find_index(const char *name)
 {
-    int i, index = -1;
-    if (*name == 'X' && *(name+1) == '-') name += 2;
+    int i;
+    if (name[0] == 'X' && *(name+1) == '-') name += 2;
     for (i = 0; encoding_name_to_id_table[i].id >= 0; i++) {
-	if (strcmp(name, encoding_name_to_id_table[i].name) == 0) {
+	if (nkf_str_caseeql(encoding_name_to_id_table[i].name, name)) {
 	    return encoding_name_to_id_table[i].id;
 	}
     }
-    return index;
+    return -1;
 }
 
-static nkf_encoding *nkf_enc_find(const char *name)
+static nkf_encoding*
+nkf_enc_find(const char *name)
 {
     int idx = -1;
     idx = nkf_enc_find_index(name);
@@ -707,19 +701,20 @@
 #define nkf_enc_to_iconv(enc) nkf_enc_to_base_encoding(enc)->iconv
 #define nkf_enc_to_oconv(enc) nkf_enc_to_base_encoding(enc)->oconv
 #define nkf_enc_asciicompat(enc) (\
-    nkf_enc_to_base_encoding(enc) == &NkfEncodingASCII ||\
-    nkf_enc_to_base_encoding(enc) == &NkfEncodingISO_2022_JP)
+				  nkf_enc_to_base_encoding(enc) == &NkfEncodingASCII ||\
+				  nkf_enc_to_base_encoding(enc) == &NkfEncodingISO_2022_JP)
 #define nkf_enc_unicode_p(enc) (\
-    nkf_enc_to_base_encoding(enc) == &NkfEncodingUTF_8 ||\
-    nkf_enc_to_base_encoding(enc) == &NkfEncodingUTF_16 ||\
-    nkf_enc_to_base_encoding(enc) == &NkfEncodingUTF_32)
+				nkf_enc_to_base_encoding(enc) == &NkfEncodingUTF_8 ||\
+				nkf_enc_to_base_encoding(enc) == &NkfEncodingUTF_16 ||\
+				nkf_enc_to_base_encoding(enc) == &NkfEncodingUTF_32)
 #define nkf_enc_cp5022x_p(enc) (\
-    nkf_enc_to_index(enc) == CP50220 ||\
-    nkf_enc_to_index(enc) == CP50221 ||\
-    nkf_enc_to_index(enc) == CP50222)
+				nkf_enc_to_index(enc) == CP50220 ||\
+				nkf_enc_to_index(enc) == CP50221 ||\
+				nkf_enc_to_index(enc) == CP50222)
 
 #ifdef DEFAULT_CODE_LOCALE
-static char* nkf_locale_charmap()
+static char*
+nkf_locale_charmap()
 {
 #ifdef HAVE_LANGINFO_H
     return nl_langinfo(CODESET);
@@ -730,7 +725,8 @@
 #endif
 }
 
-static nkf_encoding* nkf_locale_encoding()
+static nkf_encoding*
+nkf_locale_encoding()
 {
     nkf_encoding *enc = 0;
     char *encname = nkf_locale_charmap();
@@ -741,15 +737,16 @@
 }
 #endif /* DEFAULT_CODE_LOCALE */
 
-static nkf_encoding* nkf_default_encoding()
+static nkf_encoding*
+nkf_default_encoding()
 {
+    nkf_encoding *enc = 0;
 #ifdef DEFAULT_CODE_LOCALE
-    nkf_encoding *enc = nkf_locale_encoding();
-    if (enc <= 0) enc = nkf_enc_from_index(ISO_2022_JP);
+    enc = nkf_locale_encoding();
+#elif DEFAULT_ENCIDX
+    enc = nkf_enc_from_index(DEFAULT_ENCIDX);
+#endif
     return enc;
-#else
-    return nkf_enc_from_index(DEFAULT_ENCIDX);
-#endif
 }
 
 #ifndef PERL_XS
@@ -757,12 +754,14 @@
 #define fprintf dllprintf
 #endif
 
-void version(void)
+static void
+version(void)
 {
     fprintf(HELP_OUTPUT,"Network Kanji Filter Version " NKF_VERSION " (" NKF_RELEASE_DATE ") \n" COPY_RIGHT "\n");
 }
 
-void usage(void)
+static void
+usage(void)
 {
     fprintf(HELP_OUTPUT,
 	    "USAGE:  nkf(nkf32,wnkf,nkf2) -[flags] [in file] .. [out file for -O flag]\n"
@@ -830,7 +829,8 @@
     version();
 }
 
-void show_configuration(void)
+static void
+show_configuration(void)
 {
     fprintf(HELP_OUTPUT,
 	    "Summary of my nkf " NKF_VERSION " (" NKF_RELEASE_DATE ") configuration:\n"
@@ -842,12 +842,11 @@
     fprintf(HELP_OUTPUT,
 	    "    Default output encoding:     "
 #ifdef DEFAULT_CODE_LOCALE
-	    "%s\n", nkf_enc_name(nkf_default_encoding())
+	    "LOCALE (%s)\n", nkf_enc_name(nkf_default_encoding())
 #elif DEFAULT_ENCIDX
-	    "%s (%s)\n", nkf_locale_encoding() ? "LOCALE" : "DEFAULT",
-	    nkf_enc_name(nkf_default_encoding())
+	    "CONFIG (%s)\n", nkf_enc_name(nkf_default_encoding())
 #else
-            "NONE"
+	    "NONE\n"
 #endif
 	   );
     fprintf(HELP_OUTPUT,
@@ -885,7 +884,8 @@
 #endif /*PERL_XS*/
 
 #ifdef OVERWRITE
-char *get_backup_filename(const char *suffix, const char *filename)
+static char*
+get_backup_filename(const char *suffix, const char *filename)
 {
     char *backup_filename;
     int asterisk_count = 0;
@@ -915,8 +915,7 @@
 	}
 	backup_filename[j] = '\0';
     }else{
-	j = strlen(suffix) + filename_length;
-	backup_filename = malloc( + 1);
+	backup_filename = malloc(filename_length + strlen(suffix) + 1);
 	strcpy(backup_filename, filename);
 	strcat(backup_filename, suffix);
 	backup_filename[j] = '\0';
@@ -926,7 +925,8 @@
 #endif
 
 #ifdef UTF8_INPUT_ENABLE
-void nkf_each_char_to_hex(void (*f)(nkf_char c2,nkf_char c1), nkf_char c)
+static void
+nkf_each_char_to_hex(void (*f)(nkf_char c2,nkf_char c1), nkf_char c)
 {
     int shift = 20;
     c &= VALUE_MASK;
@@ -943,7 +943,8 @@
     return;
 }
 
-void encode_fallback_html(nkf_char c)
+static void
+encode_fallback_html(nkf_char c)
 {
     (*oconv)(0, '&');
     (*oconv)(0, '#');
@@ -966,7 +967,8 @@
     return;
 }
 
-void encode_fallback_xml(nkf_char c)
+static void
+encode_fallback_xml(nkf_char c)
 {
     (*oconv)(0, '&');
     (*oconv)(0, '#');
@@ -976,11 +978,12 @@
     return;
 }
 
-void encode_fallback_java(nkf_char c)
+static void
+encode_fallback_java(nkf_char c)
 {
     (*oconv)(0, '\\');
     c &= VALUE_MASK;
-    if(!is_unicode_bmp(c)){
+    if(!nkf_char_unicode_bmp_p(c)){
 	(*oconv)(0, 'U');
 	(*oconv)(0, '0');
 	(*oconv)(0, '0');
@@ -996,7 +999,8 @@
     return;
 }
 
-void encode_fallback_perl(nkf_char c)
+static void
+encode_fallback_perl(nkf_char c)
 {
     (*oconv)(0, '\\');
     (*oconv)(0, 'x');
@@ -1006,7 +1010,8 @@
     return;
 }
 
-void encode_fallback_subchar(nkf_char c)
+static void
+encode_fallback_subchar(nkf_char c)
 {
     c = unicode_subchar;
     (*oconv)((c>>8)&0xFF, c&0xFF);
@@ -1094,9 +1099,13 @@
     {"prefix=", ""},
 };
 
-static void set_input_encoding(nkf_encoding *enc)
+static void
+set_input_encoding(nkf_encoding *enc)
 {
     switch (nkf_enc_to_index(enc)) {
+    case ISO_8859_1:
+	iso8859_f = TRUE;
+	break;
     case CP50220:
     case CP50221:
     case CP50222:
@@ -1108,16 +1117,16 @@
 #endif
 	break;
     case ISO_2022_JP_1:
-#ifdef X0212_ENABLE
 	x0212_f = TRUE;
-#endif
 	break;
     case ISO_2022_JP_3:
-#ifdef X0212_ENABLE
 	x0212_f = TRUE;
-#endif
 	x0213_f = TRUE;
 	break;
+    case ISO_2022_JP_2004:
+	x0212_f = TRUE;
+	x0213_f = TRUE;
+	break;
     case SHIFT_JIS:
 	break;
     case WINDOWS_31J:
@@ -1128,7 +1137,6 @@
 	ms_ucs_map_f = UCS_MAP_CP932;
 #endif
 	break;
-    case EUC_JP:
 	break;
     case CP10001:
 #ifdef SHIFTJIS_CP932
@@ -1138,6 +1146,10 @@
 	ms_ucs_map_f = UCS_MAP_CP10001;
 #endif
 	break;
+    case EUC_JP:
+	break;
+    case EUCJP_NKF:
+	break;
     case CP51932:
 #ifdef SHIFTJIS_CP932
 	cp51932_f = TRUE;
@@ -1204,7 +1216,8 @@
     }
 }
 
-static void set_output_encoding(nkf_encoding *enc)
+static void
+set_output_encoding(nkf_encoding *enc)
 {
     switch (nkf_enc_to_index(enc)) {
     case CP50220:
@@ -1225,17 +1238,13 @@
 #endif
 	break;
     case ISO_2022_JP_1:
-#ifdef X0212_ENABLE
 	x0212_f = TRUE;
-#endif
 #ifdef SHIFTJIS_CP932
 	if (cp932inv_f == TRUE) cp932inv_f = FALSE;
 #endif
 	break;
     case ISO_2022_JP_3:
-#ifdef X0212_ENABLE
 	x0212_f = TRUE;
-#endif
 	x0213_f = TRUE;
 #ifdef SHIFTJIS_CP932
 	if (cp932inv_f == TRUE) cp932inv_f = FALSE;
@@ -1259,9 +1268,18 @@
 	if (cp932inv_f == TRUE) cp932inv_f = FALSE;
 #endif
 #ifdef UTF8_OUTPUT_ENABLE
-	ms_ucs_map_f = UCS_MAP_CP932;
+	ms_ucs_map_f = UCS_MAP_ASCII;
 #endif
 	break;
+    case EUCJP_NKF:
+	x0212_f = FALSE;
+#ifdef SHIFTJIS_CP932
+	if (cp932inv_f == TRUE) cp932inv_f = FALSE;
+#endif
+#ifdef UTF8_OUTPUT_ENABLE
+	ms_ucs_map_f = UCS_MAP_ASCII;
+#endif
+	break;
     case CP51932:
 #ifdef SHIFTJIS_CP932
 	if (cp932inv_f == TRUE) cp932inv_f = FALSE;
@@ -1271,17 +1289,13 @@
 #endif
 	break;
     case EUCJP_MS:
-#ifdef X0212_ENABLE
 	x0212_f = TRUE;
-#endif
 #ifdef UTF8_OUTPUT_ENABLE
 	ms_ucs_map_f = UCS_MAP_MS;
 #endif
 	break;
     case EUCJP_ASCII:
-#ifdef X0212_ENABLE
 	x0212_f = TRUE;
-#endif
 #ifdef UTF8_OUTPUT_ENABLE
 	ms_ucs_map_f = UCS_MAP_ASCII;
 #endif
@@ -1295,9 +1309,7 @@
 	break;
     case EUC_JISX0213:
     case EUC_JIS_2004:
-#ifdef X0212_ENABLE
 	x0212_f = TRUE;
-#endif
 	x0213_f = TRUE;
 #ifdef SHIFTJIS_CP932
 	if (cp932inv_f == TRUE) cp932inv_f = FALSE;
@@ -1334,79 +1346,84 @@
     }
 }
 
-struct input_code * find_inputcode_byfunc(nkf_char (*iconv_func)(nkf_char c2,nkf_char c1,nkf_char c0))
+static struct input_code*
+find_inputcode_byfunc(nkf_char (*iconv_func)(nkf_char c2,nkf_char c1,nkf_char c0))
 {
     if (iconv_func){
-        struct input_code *p = input_code_list;
-        while (p->name){
-            if (iconv_func == p->iconv_func){
-                return p;
-            }
-            p++;
-        }
+	struct input_code *p = input_code_list;
+	while (p->name){
+	    if (iconv_func == p->iconv_func){
+		return p;
+	    }
+	    p++;
+	}
     }
     return 0;
 }
 
-void set_iconv(nkf_char f, nkf_char (*iconv_func)(nkf_char c2,nkf_char c1,nkf_char c0))
+static void
+set_iconv(nkf_char f, nkf_char (*iconv_func)(nkf_char c2,nkf_char c1,nkf_char c0))
 {
 #ifdef INPUT_CODE_FIX
     if (f || !input_encoding)
 #endif
-        if (estab_f != f){
-            estab_f = f;
-        }
+	if (estab_f != f){
+	    estab_f = f;
+	}
 
     if (iconv_func
 #ifdef INPUT_CODE_FIX
-        && (f == -TRUE || !input_encoding) /* -TRUE means "FORCE" */
+	&& (f == -TRUE || !input_encoding) /* -TRUE means "FORCE" */
 #endif
-        ){
-        iconv = iconv_func;
+       ){
+	iconv = iconv_func;
     }
 #ifdef CHECK_OPTION
     if (estab_f && iconv_for_check != iconv){
-        struct input_code *p = find_inputcode_byfunc(iconv);
-        if (p){
-            set_input_codename(p->name);
-            debug(p->name);
-        }
-        iconv_for_check = iconv;
+	struct input_code *p = find_inputcode_byfunc(iconv);
+	if (p){
+	    set_input_codename(p->name);
+	    debug(p->name);
+	}
+	iconv_for_check = iconv;
     }
 #endif
 }
 
 #ifdef X0212_ENABLE
-nkf_char x0212_shift(nkf_char c)
+static nkf_char
+x0212_shift(nkf_char c)
 {
     nkf_char ret = c;
     c &= 0x7f;
     if (is_eucg3(ret)){
-        if (0x75 <= c && c <= 0x7f){
-            ret = c + (0x109 - 0x75);
-        }
+	if (0x75 <= c && c <= 0x7f){
+	    ret = c + (0x109 - 0x75);
+	}
     }else{
-        if (0x75 <= c && c <= 0x7f){
-            ret = c + (0x113 - 0x75);
-        }
+	if (0x75 <= c && c <= 0x7f){
+	    ret = c + (0x113 - 0x75);
+	}
     }
     return ret;
 }
 
 
-nkf_char x0212_unshift(nkf_char c)
+static nkf_char
+x0212_unshift(nkf_char c)
 {
     nkf_char ret = c;
     if (0x7f <= c && c <= 0x88){
-        ret = c + (0x75 - 0x7f);
+	ret = c + (0x75 - 0x7f);
     }else if (0x89 <= c && c <= 0x92){
-        ret = PREFIX_EUCG3 | 0x80 | (c + (0x75 - 0x89));
+	ret = PREFIX_EUCG3 | 0x80 | (c + (0x75 - 0x89));
     }
     return ret;
 }
 #endif /* X0212_ENABLE */
 
-nkf_char e2s_conv(nkf_char c2, nkf_char c1, nkf_char *p2, nkf_char *p1)
+static nkf_char
+e2s_conv(nkf_char c2, nkf_char c1, nkf_char *p2, nkf_char *p1)
 {
     nkf_char ndx;
     if (is_eucg3(c2)){
@@ -1448,7 +1465,8 @@
     return 0;
 }
 
-nkf_char s2e_conv(nkf_char c2, nkf_char c1, nkf_char *p2, nkf_char *p1)
+static nkf_char
+s2e_conv(nkf_char c2, nkf_char c1, nkf_char *p2, nkf_char *p1)
 {
 #if defined(SHIFTJIS_CP932) || defined(X0212_ENABLE)
     nkf_char val;
@@ -1456,36 +1474,36 @@
     static const char shift_jisx0213_s1a3_table[5][2] ={ { 1, 8}, { 3, 4}, { 5,12}, {13,14}, {15, 0} };
 #ifdef SHIFTJIS_CP932
     if (!cp932inv_f && is_ibmext_in_sjis(c2)){
-        val = shiftjis_cp932[c2 - CP932_TABLE_BEGIN][c1 - 0x40];
-        if (val){
-            c2 = val >> 8;
-            c1 = val & 0xff;
-        }
+	val = shiftjis_cp932[c2 - CP932_TABLE_BEGIN][c1 - 0x40];
+	if (val){
+	    c2 = val >> 8;
+	    c1 = val & 0xff;
+	}
     }
     if (cp932inv_f
-        && CP932INV_TABLE_BEGIN <= c2 && c2 <= CP932INV_TABLE_END){
-        nkf_char c = cp932inv[c2 - CP932INV_TABLE_BEGIN][c1 - 0x40];
-        if (c){
-            c2 = c >> 8;
-            c1 = c & 0xff;
-        }
+	&& CP932INV_TABLE_BEGIN <= c2 && c2 <= CP932INV_TABLE_END){
+	nkf_char c = cp932inv[c2 - CP932INV_TABLE_BEGIN][c1 - 0x40];
+	if (c){
+	    c2 = c >> 8;
+	    c1 = c & 0xff;
+	}
     }
 #endif /* SHIFTJIS_CP932 */
 #ifdef X0212_ENABLE
     if (!x0213_f && is_ibmext_in_sjis(c2)){
-        val = shiftjis_x0212[c2 - 0xfa][c1 - 0x40];
-        if (val){
-            if (val > 0x7FFF){
-                c2 = PREFIX_EUCG3 | ((val >> 8) & 0x7f);
-                c1 = val & 0xff;
-            }else{
-                c2 = val >> 8;
-                c1 = val & 0xff;
-            }
-            if (p2) *p2 = c2;
-            if (p1) *p1 = c1;
-            return 0;
-        }
+	val = shiftjis_x0212[c2 - 0xfa][c1 - 0x40];
+	if (val){
+	    if (val > 0x7FFF){
+		c2 = PREFIX_EUCG3 | ((val >> 8) & 0x7f);
+		c1 = val & 0xff;
+	    }else{
+		c2 = val >> 8;
+		c1 = val & 0xff;
+	    }
+	    if (p2) *p2 = c2;
+	    if (p1) *p1 = c1;
+	    return 0;
+	}
     }
 #endif
     if(c2 >= 0x80){
@@ -1518,59 +1536,80 @@
 }
 
 #if defined(UTF8_INPUT_ENABLE) || defined(UTF8_OUTPUT_ENABLE)
-void w16w_conv(nkf_char val, nkf_char *p2, nkf_char *p1, nkf_char *p0)
+static void
+nkf_unicode_to_utf8(nkf_char val, int *p1, int *p2, int *p3, int *p4)
 {
     val &= VALUE_MASK;
     if (val < 0x80){
-        *p2 = val;
-        *p1 = 0;
-        *p0 = 0;
+	*p1 = val;
+	*p2 = 0;
+	*p3 = 0;
+	*p4 = 0;
     }else if (val < 0x800){
-	*p2 = 0xc0 | (val >> 6);
-	*p1 = 0x80 | (val & 0x3f);
-        *p0 = 0;
-    } else if (val <= NKF_INT32_C(0xFFFF)) {
-        *p2 = 0xe0 | (val >> 12);
-        *p1 = 0x80 | ((val >> 6) & 0x3f);
-        *p0 = 0x80 | (val        & 0x3f);
-    } else if (val <= NKF_INT32_C(0x10FFFF)) {
-        *p2 = 0xe0 |  (val >> 16);
-        *p1 = 0x80 | ((val >> 12) & 0x3f);
-        *p0 = 0x8080 | ((val << 2) & 0x3f00)| (val & 0x3f);
+	*p1 = 0xc0 | (val >> 6);
+	*p2 = 0x80 | (val & 0x3f);
+	*p3 = 0;
+	*p4 = 0;
+    } else if (nkf_char_unicode_bmp_p(val)) {
+	*p1 = 0xe0 |  (val >> 12);
+	*p2 = 0x80 | ((val >>  6) & 0x3f);
+	*p3 = 0x80 | ( val        & 0x3f);
+	*p4 = 0;
+    } else if (nkf_char_unicode_value_p(val)) {
+	*p1 = 0xe0 |  (val >> 16);
+	*p2 = 0x80 | ((val >> 12) & 0x3f);
+	*p3 = 0x80 | ((val >>  6) & 0x3f);
+	*p4 = 0x80 | ( val        & 0x3f);
     } else {
-        *p2 = 0;
-        *p1 = 0;
-        *p0 = 0;
+	*p1 = 0;
+	*p2 = 0;
+	*p3 = 0;
+	*p4 = 0;
     }
 }
 
-nkf_char ww16_conv(nkf_char c2, nkf_char c1, nkf_char c0)
+static nkf_char
+nkf_utf8_to_unicode(int c1, int c2, int c3, int c4)
 {
-    nkf_char val;
-    if (c2 >= 0xf8) {
-	val = -1;
-    } else if (c2 >= 0xf0){
-	/* c2: 1st, c1: 2nd, c0: 3rd/4th */
-	val = (c2 & 0x0f) << 18;
-        val |= (c1 & 0x3f) << 12;
-        val |= (c0 & 0x3f00) >> 2;
-        val |= (c0 & 0x3f);
-    }else if (c2 >= 0xe0){
-        val = (c2 & 0x0f) << 12;
-        val |= (c1 & 0x3f) << 6;
-        val |= (c0 & 0x3f);
-    }else if (c2 >= 0xc0){
-        val = (c2 & 0x1f) << 6;
-        val |= (c1 & 0x3f);
-    }else{
-        val = c2;
+    nkf_char wc;
+    if (c1 <= 0x7F) {
+	/* single byte */
+	wc = c1;
     }
-    return val;
+    else if (c1 <= 0xC3) {
+	/* trail byte or invalid */
+	return -1;
+    }
+    else if (c1 <= 0xDF) {
+	/* 2 bytes */
+	wc  = (c1 & 0x1F) << 6;
+	wc |= (c2 & 0x3F);
+    }
+    else if (c1 <= 0xEF) {
+	/* 3 bytes */
+	wc  = (c1 & 0x0F) << 12;
+	wc |= (c2 & 0x3F) << 6;
+	wc |= (c3 & 0x3F);
+    }
+    else if (c2 <= 0xF4) {
+	/* 4 bytes */
+	wc  = (c1 & 0x0F) << 18;
+	wc |= (c2 & 0x3F) << 12;
+	wc |= (c3 & 0x3F) << 6;
+	wc |= (c4 & 0x3F);
+    }
+    else {
+	return -1;
+    }
+    return wc;
 }
 #endif
 
 #ifdef UTF8_INPUT_ENABLE
-nkf_char w_iconv_common(nkf_char c1, nkf_char c0, const unsigned short *const *pp, nkf_char psize, nkf_char *p2, nkf_char *p1)
+static int
+unicode_to_jis_common2(nkf_char c1, nkf_char c0,
+		       const unsigned short *const *pp, nkf_char psize,
+		       nkf_char *p2, nkf_char *p1)
 {
     nkf_char c2;
     const unsigned short *p;
@@ -1588,23 +1627,24 @@
     val = p[c0];
     if (val == 0) return 1;
     if (no_cp932ext_f && (
-	(val>>8) == 0x2D || /* NEC special characters */
-	val > NKF_INT32_C(0xF300) /* IBM extended characters */
-	)) return 1;
+			  (val>>8) == 0x2D || /* NEC special characters */
+			  val > NKF_INT32_C(0xF300) /* IBM extended characters */
+			 )) return 1;
 
     c2 = val >> 8;
-   if (val > 0x7FFF){
-        c2 &= 0x7f;
-        c2 |= PREFIX_EUCG3;
+    if (val > 0x7FFF){
+	c2 &= 0x7f;
+	c2 |= PREFIX_EUCG3;
     }
-    if (c2 == SO) c2 = JIS_X_0201;
-    c1 = val & 0x7f;
+    if (c2 == SO) c2 = JIS_X_0201_1976_K;
+    c1 = val & 0xFF;
     if (p2) *p2 = c2;
     if (p1) *p1 = c1;
     return 0;
 }
 
-nkf_char unicode_to_jis_common(nkf_char c2, nkf_char c1, nkf_char c0, nkf_char *p2, nkf_char *p1)
+static int
+unicode_to_jis_common(nkf_char c2, nkf_char c1, nkf_char c0, nkf_char *p2, nkf_char *p1)
 {
     const unsigned short *const *pp;
     const unsigned short *const *const *ppp;
@@ -1677,7 +1717,7 @@
 	    ms_ucs_map_f == UCS_MAP_MS ? utf8_to_euc_2bytes_ms :
 	    ms_ucs_map_f == UCS_MAP_CP10001 ? utf8_to_euc_2bytes_mac :
 	    utf8_to_euc_2bytes;
-	ret =  w_iconv_common(c2, c1, pp, sizeof_utf8_to_euc_2bytes, p2, p1);
+	ret =  unicode_to_jis_common2(c2, c1, pp, sizeof_utf8_to_euc_2bytes, p2, p1);
     }else if(c0 < 0xF0){
 	if(no_best_fit_chars_f){
 	    if(ms_ucs_map_f == UCS_MAP_CP932){
@@ -1703,10 +1743,10 @@
 		case 0xE3:
 		    switch(c1){
 		    case 0x82:
-			    if(c0 == 0x94) return 1;
+			if(c0 == 0x94) return 1;
 			break;
 		    case 0x83:
-			    if(c0 == 0xBB) return 1;
+			if(c0 == 0xBB) return 1;
 			break;
 		    }
 		    break;
@@ -1744,7 +1784,7 @@
 	    ms_ucs_map_f == UCS_MAP_MS ? utf8_to_euc_3bytes_ms :
 	    ms_ucs_map_f == UCS_MAP_CP10001 ? utf8_to_euc_3bytes_mac :
 	    utf8_to_euc_3bytes;
-	ret = w_iconv_common(c1, c0, ppp[c2 - 0xE0], sizeof_utf8_to_euc_C2, p2, p1);
+	ret = unicode_to_jis_common2(c1, c0, ppp[c2 - 0xE0], sizeof_utf8_to_euc_C2, p2, p1);
     }else return -1;
 #ifdef SHIFTJIS_CP932
     if (!ret && !cp932inv_f && is_eucg3(*p2)) {
@@ -1760,11 +1800,12 @@
 }
 
 #ifdef UTF8_OUTPUT_ENABLE
-nkf_char e2w_conv(nkf_char c2, nkf_char c1)
+static nkf_char
+e2w_conv(nkf_char c2, nkf_char c1)
 {
     const unsigned short *p;
 
-    if (c2 == JIS_X_0201) {
+    if (c2 == JIS_X_0201_1976_K) {
 	if (ms_ucs_map_f == UCS_MAP_CP10001) {
 	    switch (c1) {
 	    case 0x20:
@@ -1773,23 +1814,23 @@
 		return 0xA9;
 	    }
 	}
-        p = euc_to_utf8_1byte;
+	p = euc_to_utf8_1byte;
 #ifdef X0212_ENABLE
     } else if (is_eucg3(c2)){
 	if(ms_ucs_map_f == UCS_MAP_ASCII&& c2 == NKF_INT32_C(0x8F22) && c1 == 0x43){
 	    return 0xA6;
 	}
-        c2 = (c2&0x7f) - 0x21;
-        if (0<=c2 && c2<sizeof_euc_to_utf8_2bytes)
+	c2 = (c2&0x7f) - 0x21;
+	if (0<=c2 && c2<sizeof_euc_to_utf8_2bytes)
 	    p = x0212_to_utf8_2bytes[c2];
-        else
-            return 0;
+	else
+	    return 0;
 #endif
     } else {
-        c2 &= 0x7f;
-        c2 = (c2&0x7f) - 0x21;
-        if (0<=c2 && c2<sizeof_euc_to_utf8_2bytes)
-            p =
+	c2 &= 0x7f;
+	c2 = (c2&0x7f) - 0x21;
+	if (0<=c2 && c2<sizeof_euc_to_utf8_2bytes)
+	    p =
 		ms_ucs_map_f == UCS_MAP_ASCII ? euc_to_utf8_2bytes[c2] :
 		ms_ucs_map_f == UCS_MAP_CP10001 ? euc_to_utf8_2bytes_mac[c2] :
 		euc_to_utf8_2bytes_ms[c2];
@@ -1804,62 +1845,73 @@
 }
 #endif
 
-nkf_char w2e_conv(nkf_char c2, nkf_char c1, nkf_char c0, nkf_char *p2, nkf_char *p1)
+static nkf_char
+w2e_conv(nkf_char c2, nkf_char c1, nkf_char c0, nkf_char *p2, nkf_char *p1)
 {
     nkf_char ret = 0;
 
     if (!c1){
-        *p2 = 0;
-        *p1 = c2;
+	*p2 = 0;
+	*p1 = c2;
     }else if (0xc0 <= c2 && c2 <= 0xef) {
 	ret =  unicode_to_jis_common(c2, c1, c0, p2, p1);
 #ifdef NUMCHAR_OPTION
-        if (ret > 0){
-            if (p2) *p2 = 0;
-            if (p1) *p1 = CLASS_UNICODE | ww16_conv(c2, c1, c0);
-            ret = 0;
-        }
+	if (ret > 0){
+	    if (p2) *p2 = 0;
+	    if (p1) *p1 = nkf_char_unicode_new(nkf_utf8_to_unicode(c2, c1, c0, 0));
+	    ret = 0;
+	}
 #endif
     }
     return ret;
 }
 
 #ifdef UTF8_INPUT_ENABLE
-nkf_char w16e_conv(nkf_char val, nkf_char *p2, nkf_char *p1)
+static nkf_char
+w16e_conv(nkf_char val, nkf_char *p2, nkf_char *p1)
 {
-    nkf_char c2, c1, c0;
+    int c1, c2, c3, c4;
     nkf_char ret = 0;
     val &= VALUE_MASK;
-    if (val < 0x80){
-        *p2 = 0;
-        *p1 = val;
-    }else{
-	w16w_conv(val, &c2, &c1, &c0);
-	ret =  unicode_to_jis_common(c2, c1, c0, p2, p1);
-#ifdef NUMCHAR_OPTION
+    if (val < 0x80) {
+	*p2 = 0;
+	*p1 = val;
+    }
+    else if (nkf_char_unicode_bmp_p(val)){
+	nkf_unicode_to_utf8(val, &c1, &c2, &c3, &c4);
+	ret =  unicode_to_jis_common(c1, c2, c3, p2, p1);
 	if (ret > 0){
 	    *p2 = 0;
-	    *p1 = CLASS_UNICODE | val;
+	    *p1 = nkf_char_unicode_new(val);
 	    ret = 0;
 	}
-#endif
     }
+    else {
+	*p2 = 0;
+	*p1 = nkf_char_unicode_new(val);
+    }
     return ret;
 }
 #endif
 
-nkf_char e_iconv(nkf_char c2, nkf_char c1, nkf_char c0)
+static nkf_char
+e_iconv(nkf_char c2, nkf_char c1, nkf_char c0)
 {
-    if (c2 == JIS_X_0201) {
-	c1 &= 0x7f;
+    if (c2 == JIS_X_0201_1976_K || c2 == SS2){
+	if (iso2022jp_f && !x0201_f) {
+	    c2 = GETA1; c1 = GETA2;
+	} else {
+	    c2 = JIS_X_0201_1976_K;
+	    c1 &= 0x7f;
+	}
 #ifdef X0212_ENABLE
     }else if (c2 == 0x8f){
-        if (c0 == 0){
-            return -1;
-        }
+	if (c0 == 0){
+	    return -1;
+	}
 	if (!cp51932_f && !x0213_f && 0xF5 <= c1 && c1 <= 0xFE && 0xA1 <= c0 && c0 <= 0xFE) {
 	    /* encoding is eucJP-ms, so invert to Unicode Private User Area */
-	    c1 = (c1 - 0xF5) * 94 + c0 - 0xA1 + 0xE3AC + CLASS_UNICODE;
+	    c1 = nkf_char_unicode_new((c1 - 0xF5) * 94 + c0 - 0xA1 + 0xE3AC);
 	    c2 = 0;
 	} else {
 	    c2 = (c2 << 8) | (c1 & 0x7f);
@@ -1876,17 +1928,14 @@
 		}
 	    }
 #endif /* SHIFTJIS_CP932 */
-        }
+	}
 #endif /* X0212_ENABLE */
-    } else if (c2 == SSO){
-        c2 = JIS_X_0201;
-        c1 &= 0x7f;
-    } else if ((c2 == EOF) || (c2 == 0) || c2 < SP) {
-        /* NOP */
+    } else if ((c2 == EOF) || (c2 == 0) || c2 < SP || c2 == ISO_8859_1) {
+	/* NOP */
     } else {
 	if (!cp51932_f && ms_ucs_map_f && 0xF5 <= c2 && c2 <= 0xFE && 0xA1 <= c1 && c1 <= 0xFE) {
 	    /* encoding is eucJP-ms, so invert to Unicode Private User Area */
-	    c1 = (c2 - 0xF5) * 94 + c1 - 0xA1 + 0xE000 + CLASS_UNICODE;
+	    c1 = nkf_char_unicode_new((c2 - 0xF5) * 94 + c1 - 0xA1 + 0xE000);
 	    c2 = 0;
 	} else {
 	    c1 &= 0x7f;
@@ -1903,34 +1952,40 @@
 		}
 	    }
 #endif /* SHIFTJIS_CP932 */
-        }
+	}
     }
     (*oconv)(c2, c1);
     return 0;
 }
 
-nkf_char s_iconv(nkf_char c2, nkf_char c1, nkf_char c0)
+static nkf_char
+s_iconv(nkf_char c2, nkf_char c1, nkf_char c0)
 {
-    if (c2 == JIS_X_0201) {
-	c1 &= 0x7f;
+    if (c2 == JIS_X_0201_1976_K || (0xA1 <= c2 && c2 <= 0xDF)) {
+	if (iso2022jp_f && !x0201_f) {
+	    c2 = GETA1; c1 = GETA2;
+	} else {
+	    c1 &= 0x7f;
+	}
     } else if ((c2 == EOF) || (c2 == 0) || c2 < SP) {
-        /* NOP */
+	/* NOP */
     } else if (!x0213_f && 0xF0 <= c2 && c2 <= 0xF9 && 0x40 <= c1 && c1 <= 0xFC) {
 	/* CP932 UDC */
 	if(c1 == 0x7F) return 0;
-	c1 = (c2 - 0xF0) * 188 + (c1 - 0x40 - (0x7E < c1)) + 0xE000 + CLASS_UNICODE;
+	c1 = nkf_char_unicode_new((c2 - 0xF0) * 188 + (c1 - 0x40 - (0x7E < c1)) + 0xE000);
 	c2 = 0;
     } else {
-        nkf_char ret = s2e_conv(c2, c1, &c2, &c1);
-        if (ret) return ret;
+	nkf_char ret = s2e_conv(c2, c1, &c2, &c1);
+	if (ret) return ret;
     }
     (*oconv)(c2, c1);
     return 0;
 }
 
-nkf_char w_iconv(nkf_char c2, nkf_char c1, nkf_char c0)
+static nkf_char
+w_iconv(nkf_char c1, nkf_char c2, nkf_char c3)
 {
-    nkf_char ret = 0;
+    nkf_char ret = 0, c4 = 0;
     static const char w_iconv_utf8_1st_byte[] =
     { /* 0xC0 - 0xFF */
 	20, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
@@ -1938,45 +1993,50 @@
 	30, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 32, 33, 33,
 	40, 41, 41, 41, 42, 43, 43, 43, 50, 50, 50, 50, 60, 60, 70, 70};
 
-    if (c2 < 0 || 0xff < c2) {
-    }else if (c2 == 0) { /* 0 : 1 byte*/
-	c0 = 0;
-    } else if ((c2 & 0xc0) == 0x80) { /* 0x80-0xbf : trail byte */
+    if (c3 > 0xFF) {
+	c4 = c3 & 0xFF;
+	c3 >>= 8;
+    }
+
+    if (c1 < 0 || 0xff < c1) {
+    }else if (c1 == 0) { /* 0 : 1 byte*/
+	c3 = 0;
+    } else if ((c1 & 0xC0) == 0x80) { /* 0x80-0xbf : trail byte */
 	return 0;
     } else{
-    	switch (w_iconv_utf8_1st_byte[c2 - 0xC0]) {
+	switch (w_iconv_utf8_1st_byte[c1 - 0xC0]) {
 	case 21:
-	    if (c1 < 0x80 || 0xBF < c1) return 0;
+	    if (c2 < 0x80 || 0xBF < c2) return 0;
 	    break;
 	case 30:
-	    if (c0 == 0) return -1;
-	    if (c1 < 0xA0 || 0xBF < c1 || (c0 & 0xc0) != 0x80)
+	    if (c3 == 0) return -1;
+	    if (c2 < 0xA0 || 0xBF < c2 || (c3 & 0xC0) != 0x80)
 		return 0;
 	    break;
 	case 31:
 	case 33:
-	    if (c0 == 0) return -1;
-	    if ((c1 & 0xc0) != 0x80 || (c0 & 0xc0) != 0x80)
+	    if (c3 == 0) return -1;
+	    if ((c2 & 0xC0) != 0x80 || (c3 & 0xC0) != 0x80)
 		return 0;
 	    break;
 	case 32:
-	    if (c0 == 0) return -1;
-	    if (c1 < 0x80 || 0x9F < c1 || (c0 & 0xc0) != 0x80)
+	    if (c3 == 0) return -1;
+	    if (c2 < 0x80 || 0x9F < c2 || (c3 & 0xC0) != 0x80)
 		return 0;
 	    break;
 	case 40:
-	    if (c0 == 0) return -2;
-	    if (c1 < 0x90 || 0xBF < c1 || (c0 & 0xc0c0) != 0x8080)
+	    if (c3 == 0) return -2;
+	    if (c2 < 0x90 || 0xBF < c2 || (c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
 		return 0;
 	    break;
 	case 41:
-	    if (c0 == 0) return -2;
-	    if (c1 < 0x80 || 0xBF < c1 || (c0 & 0xc0c0) != 0x8080)
+	    if (c3 == 0) return -2;
+	    if (c2 < 0x80 || 0xBF < c2 || (c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
 		return 0;
 	    break;
 	case 42:
-	    if (c0 == 0) return -2;
-	    if (c1 < 0x80 || 0x8F < c1 || (c0 & 0xc0c0) != 0x8080)
+	    if (c3 == 0) return -2;
+	    if (c2 < 0x80 || 0x8F < c2 || (c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
 		return 0;
 	    break;
 	default:
@@ -1984,65 +2044,181 @@
 	    break;
 	}
     }
-    if (c2 == 0 || c2 == EOF){
-    } else if ((c2 & 0xf8) == 0xf0) { /* 4 bytes */
-	c1 = CLASS_UNICODE | ww16_conv(c2, c1, c0);
-	c2 = 0;
+    if (c1 == 0 || c1 == EOF){
+    } else if ((c1 & 0xf8) == 0xf0) { /* 4 bytes */
+	c2 = nkf_char_unicode_new(nkf_utf8_to_unicode(c1, c2, c3, c4));
+	c1 = 0;
     } else {
-	ret = w2e_conv(c2, c1, c0, &c2, &c1);
+	ret = w2e_conv(c1, c2, c3, &c1, &c2);
     }
     if (ret == 0){
-        (*oconv)(c2, c1);
+	(*oconv)(c1, c2);
     }
     return ret;
 }
 
-nkf_char w_iconv16(nkf_char c2, nkf_char c1, nkf_char c0)
+#define NKF_ICONV_INVALID_CODE_RANGE -13
+static size_t
+unicode_iconv(nkf_char wc)
 {
-    nkf_char ret = 0;
-    if ((c2==0 && c1 < 0x80) || c2==EOF) {
-	(*oconv)(c2, c1);
-	return 0;
-    }else if (0xD8 <= c2 && c2 <= 0xDB) {
-	if (c0 < NKF_INT32_C(0xDC00) || NKF_INT32_C(0xDFFF) < c0)
-	    return -2;
-	c1 =  CLASS_UNICODE | ((c2 << 18) + (c1 << 10) + c0 - NKF_INT32_C(0x35FDC00));
+    nkf_char c1, c2;
+    int ret = 0;
+
+    if (wc < 0x80) {
 	c2 = 0;
-    }else if ((c2>>3) == 27) { /* unpaired surrogate */
-	/*
-	   return 2;
-	*/
-	return 1;
-    }else ret = w16e_conv(((c2 & 0xff)<<8) + c1, &c2, &c1);
-    if (ret) return ret;
+	c1 = wc;
+    }else if ((wc>>11) == 27) {
+	/* unpaired surrogate */
+	return NKF_ICONV_INVALID_CODE_RANGE;
+    }else if (wc < 0xFFFF) {
+	ret = w16e_conv(wc, &c2, &c1);
+	if (ret) return ret;
+    }else if (wc < 0x10FFFF) {
+	c2 = 0;
+	c1 = nkf_char_unicode_new(wc);
+    } else {
+	return NKF_ICONV_INVALID_CODE_RANGE;
+    }
     (*oconv)(c2, c1);
     return 0;
 }
 
-nkf_char w_iconv32(nkf_char c2, nkf_char c1, nkf_char c0)
+#define NKF_ICONV_NEED_ONE_MORE_BYTE -1
+#define NKF_ICONV_NEED_TWO_MORE_BYTES -2
+#define UTF16_TO_UTF32(lead, trail) (((lead) << 10) + (trail) - NKF_INT32_C(0x35FDC00))
+static size_t
+nkf_iconv_utf_16(int c1, int c2, int c3, int c4)
 {
-    int ret = 0;
+    nkf_char wc;
 
-    if ((c2 == 0 && c1 < 0x80) || c2==EOF) {
-    } else if (is_unicode_bmp(c1)) {
-	ret = w16e_conv(c1, &c2, &c1);
+    if (c1 == EOF) {
+	(*oconv)(EOF, 0);
+	return 0;
+    }
+
+    if (input_endian == ENDIAN_BIG) {
+	if (0xD8 <= c1 && c1 <= 0xDB) {
+	    if (0xDC <= c3 && c3 <= 0xDF) {
+		wc = UTF16_TO_UTF32(c1 << 8 | c2, c3 << 8 | c4);
+	    } else return NKF_ICONV_NEED_TWO_MORE_BYTES;
+	} else {
+	    wc = c1 << 8 | c2;
+	}
     } else {
-	c2 = 0;
-	c1 =  CLASS_UNICODE | c1;
+	if (0xD8 <= c2 && c2 <= 0xDB) {
+	    if (0xDC <= c4 && c4 <= 0xDF) {
+		wc = UTF16_TO_UTF32(c2 << 8 | c1, c4 << 8 | c3);
+	    } else return NKF_ICONV_NEED_TWO_MORE_BYTES;
+	} else {
+	    wc = c2 << 8 | c1;
+	}
     }
-    if (ret) return ret;
-    (*oconv)(c2, c1);
+
+    return (*unicode_iconv)(wc);
+}
+
+static nkf_char
+w_iconv16(nkf_char c2, nkf_char c1, nkf_char c0)
+{
     return 0;
 }
 
+static nkf_char
+w_iconv32(nkf_char c2, nkf_char c1, nkf_char c0)
+{
+    return 0;
+}
+
+static size_t
+nkf_iconv_utf_32(int c1, int c2, int c3, int c4)
+{
+    nkf_char wc;
+
+    if (c1 == EOF) {
+	(*oconv)(EOF, 0);
+	return 0;
+    }
+
+    switch(input_endian){
+    case ENDIAN_BIG:
+	wc = c2 << 16 | c3 << 8 | c4;
+	break;
+    case ENDIAN_LITTLE:
+	wc = c3 << 16 | c2 << 8 | c1;
+	break;
+    case ENDIAN_2143:
+	wc = c1 << 16 | c4 << 8 | c3;
+	break;
+    case ENDIAN_3412:
+	wc = c4 << 16 | c1 << 8 | c2;
+	break;
+    default:
+	return NKF_ICONV_INVALID_CODE_RANGE;
+    }
+
+    return (*unicode_iconv)(wc);
+}
 #endif
 
-void j_oconv(nkf_char c2, nkf_char c1)
+#define output_ascii_escape_sequence(mode) do { \
+	    if (output_mode != ASCII && output_mode != ISO_8859_1) { \
+		    (*o_putc)(ESC); \
+		    (*o_putc)('('); \
+		    (*o_putc)(ascii_intro); \
+		    output_mode = mode; \
+	    } \
+    } while (0)
+
+static void
+output_escape_sequence(int mode)
 {
+    if (output_mode == mode)
+	return;
+    switch(mode) {
+    case ISO_8859_1:
+	(*o_putc)(ESC);
+	(*o_putc)('.');
+	(*o_putc)('A');
+	break;
+    case JIS_X_0201_1976_K:
+	(*o_putc)(ESC);
+	(*o_putc)('(');
+	(*o_putc)('I');
+	break;
+    case JIS_X_0208:
+	(*o_putc)(ESC);
+	(*o_putc)('$');
+	(*o_putc)(kanji_intro);
+	break;
+    case JIS_X_0212:
+	(*o_putc)(ESC);
+	(*o_putc)('$');
+	(*o_putc)('(');
+	(*o_putc)('D');
+	break;
+    case JIS_X_0213_1:
+	(*o_putc)(ESC);
+	(*o_putc)('$');
+	(*o_putc)('(');
+	(*o_putc)('Q');
+	break;
+    case JIS_X_0213_2:
+	(*o_putc)(ESC);
+	(*o_putc)('$');
+	(*o_putc)('(');
+	(*o_putc)('P');
+	break;
+    }
+    output_mode = mode;
+}
+
+static void
+j_oconv(nkf_char c2, nkf_char c1)
+{
 #ifdef NUMCHAR_OPTION
-    if (c2 == 0 && is_unicode_capsule(c1)){
-        w16e_conv(c1, &c2, &c1);
-        if (c2 == 0 && is_unicode_capsule(c1)){
+    if (c2 == 0 && nkf_char_unicode_p(c1)){
+	w16e_conv(c1, &c2, &c1);
+	if (c2 == 0 && nkf_char_unicode_p(c1)){
 	    c2 = c1 & VALUE_MASK;
 	    if (ms_ucs_map_f && 0xE000 <= c2 && c2 <= 0xE757) {
 		/* CP5022x UDC */
@@ -2053,90 +2229,46 @@
 		if (encode_fallback) (*encode_fallback)(c1);
 		return;
 	    }
-        }
+	}
     }
 #endif
-    if (c2 == EOF) {
-        if (output_mode !=ASCII && output_mode!=ISO_8859_1) {
-            (*o_putc)(ESC);
-            (*o_putc)('(');
-            (*o_putc)(ascii_intro);
-	    output_mode = ASCII;
-        }
-        (*o_putc)(EOF);
+    if (c2 == 0) {
+	output_ascii_escape_sequence(ASCII);
+	(*o_putc)(c1);
+    }
+    else if (c2 == EOF) {
+	output_ascii_escape_sequence(ASCII);
+	(*o_putc)(EOF);
+    }
+    else if (c2 == ISO_8859_1) {
+	output_ascii_escape_sequence(ISO_8859_1);
+	(*o_putc)(c1|0x80);
+    }
+    else if (c2 == JIS_X_0201_1976_K) {
+	output_escape_sequence(JIS_X_0201_1976_K);
+	(*o_putc)(c1);
 #ifdef X0212_ENABLE
     } else if (is_eucg3(c2)){
-	if(x0213_f){
-	    if(output_mode!=JIS_X_0213_2){
-		output_mode = JIS_X_0213_2;
-		(*o_putc)(ESC);
-		(*o_putc)('$');
-		(*o_putc)('(');
-		(*o_putc)(0x50);
-	    }
-	}else{
-	    if(output_mode!=JIS_X_0212){
-		output_mode = JIS_X_0212;
-		(*o_putc)(ESC);
-		(*o_putc)('$');
-		(*o_putc)('(');
-		(*o_putc)(0x44);
-	    }
-        }
-        (*o_putc)(c2 & 0x7f);
-        (*o_putc)(c1);
+	output_escape_sequence(x0213_f ? JIS_X_0213_2 : JIS_X_0212);
+	(*o_putc)(c2 & 0x7f);
+	(*o_putc)(c1);
 #endif
-    } else if (c2==JIS_X_0201) {
-        if (output_mode!=JIS_X_0201) {
-            output_mode = JIS_X_0201;
-            (*o_putc)(ESC);
-            (*o_putc)('(');
-            (*o_putc)('I');
-        }
-        (*o_putc)(c1);
-    } else if (c2==ISO_8859_1) {
-            /* iso8859 introduction, or 8th bit on */
-            /* Can we convert in 7bit form using ESC-'-'-A ?
-               Is this popular? */
-	output_mode = ISO_8859_1;
-        (*o_putc)(c1|0x80);
-    } else if (c2 == 0) {
-        if (output_mode !=ASCII && output_mode!=ISO_8859_1) {
-            (*o_putc)(ESC);
-            (*o_putc)('(');
-            (*o_putc)(ascii_intro);
-            output_mode = ASCII;
-        }
-        (*o_putc)(c1);
     } else {
 	if(ms_ucs_map_f
 	   ? c2<0x20 || 0x92<c2 || c1<0x20 || 0x7e<c1
 	   : c2<0x20 || 0x7e<c2 || c1<0x20 || 0x7e<c1) return;
-	if(x0213_f){
-	    if (output_mode!=JIS_X_0213_1) {
-		output_mode = JIS_X_0213_1;
-		(*o_putc)(ESC);
-		(*o_putc)('$');
-		(*o_putc)('(');
-		(*o_putc)(0x4F);
-	    }
-	}else if (output_mode != JIS_X_0208) {
-            output_mode = JIS_X_0208;
-            (*o_putc)(ESC);
-            (*o_putc)('$');
-            (*o_putc)(kanji_intro);
-        }
-        (*o_putc)(c2);
-        (*o_putc)(c1);
+	output_escape_sequence(x0213_f ? JIS_X_0213_1 : JIS_X_0208);
+	(*o_putc)(c2);
+	(*o_putc)(c1);
     }
 }
 
-void e_oconv(nkf_char c2, nkf_char c1)
+static void
+e_oconv(nkf_char c2, nkf_char c1)
 {
-#ifdef NUMCHAR_OPTION
-    if (c2 == 0 && is_unicode_capsule(c1)){
-        w16e_conv(c1, &c2, &c1);
-        if (c2 == 0 && is_unicode_capsule(c1)){
+    if (c2 == 0 && nkf_char_unicode_p(c1)){
+	w16e_conv(c1, &c2, &c1);
+	if (c2 == 0 && nkf_char_unicode_p(c1)){
 	    c2 = c1 & VALUE_MASK;
 	    if (x0212_f && 0xE000 <= c2 && c2 <= 0xE757) {
 		/* eucJP-ms UDC */
@@ -2157,63 +2289,63 @@
 		if (encode_fallback) (*encode_fallback)(c1);
 		return;
 	    }
-        }
+	}
     }
-#endif
+
     if (c2 == EOF) {
-        (*o_putc)(EOF);
-        return;
+	(*o_putc)(EOF);
     } else if (c2 == 0) {
 	output_mode = ASCII;
-        (*o_putc)(c1);
-    } else if (c2 == JIS_X_0201) {
+	(*o_putc)(c1);
+    } else if (c2 == JIS_X_0201_1976_K) {
 	output_mode = EUC_JP;
-        (*o_putc)(SSO); (*o_putc)(c1|0x80);
+	(*o_putc)(SS2); (*o_putc)(c1|0x80);
     } else if (c2 == ISO_8859_1) {
 	output_mode = ISO_8859_1;
-        (*o_putc)(c1 | 0x080);
+	(*o_putc)(c1 | 0x080);
 #ifdef X0212_ENABLE
     } else if (is_eucg3(c2)){
 	output_mode = EUC_JP;
 #ifdef SHIFTJIS_CP932
-        if (!cp932inv_f){
-            nkf_char s2, s1;
-            if (e2s_conv(c2, c1, &s2, &s1) == 0){
-                s2e_conv(s2, s1, &c2, &c1);
-            }
-        }
+	if (!cp932inv_f){
+	    nkf_char s2, s1;
+	    if (e2s_conv(c2, c1, &s2, &s1) == 0){
+		s2e_conv(s2, s1, &c2, &c1);
+	    }
+	}
 #endif
-        if (c2 == 0) {
+	if (c2 == 0) {
 	    output_mode = ASCII;
 	    (*o_putc)(c1);
 	}else if (is_eucg3(c2)){
-            if (x0212_f){
-                (*o_putc)(0x8f);
-                (*o_putc)((c2 & 0x7f) | 0x080);
-                (*o_putc)(c1 | 0x080);
-            }
-        }else{
-            (*o_putc)((c2 & 0x7f) | 0x080);
-            (*o_putc)(c1 | 0x080);
-        }
+	    if (x0212_f){
+		(*o_putc)(0x8f);
+		(*o_putc)((c2 & 0x7f) | 0x080);
+		(*o_putc)(c1 | 0x080);
+	    }
+	}else{
+	    (*o_putc)((c2 & 0x7f) | 0x080);
+	    (*o_putc)(c1 | 0x080);
+	}
 #endif
     } else {
-        if (!nkf_isgraph(c1) || !nkf_isgraph(c2)) {
-            set_iconv(FALSE, 0);
-            return; /* too late to rescue this char */
-        }
+	if (!nkf_isgraph(c1) || !nkf_isgraph(c2)) {
+	    set_iconv(FALSE, 0);
+	    return; /* too late to rescue this char */
+	}
 	output_mode = EUC_JP;
-        (*o_putc)(c2 | 0x080);
-        (*o_putc)(c1 | 0x080);
+	(*o_putc)(c2 | 0x080);
+	(*o_putc)(c1 | 0x080);
     }
 }
 
-void s_oconv(nkf_char c2, nkf_char c1)
+static void
+s_oconv(nkf_char c2, nkf_char c1)
 {
 #ifdef NUMCHAR_OPTION
-    if (c2 == 0 && is_unicode_capsule(c1)){
-        w16e_conv(c1, &c2, &c1);
-        if (c2 == 0 && is_unicode_capsule(c1)){
+    if (c2 == 0 && nkf_char_unicode_p(c1)){
+	w16e_conv(c1, &c2, &c1);
+	if (c2 == 0 && nkf_char_unicode_p(c1)){
 	    c2 = c1 & VALUE_MASK;
 	    if (!x0213_f && 0xE000 <= c2 && c2 <= 0xE757) {
 		/* CP932 UDC */
@@ -2232,215 +2364,193 @@
     }
 #endif
     if (c2 == EOF) {
-        (*o_putc)(EOF);
-        return;
+	(*o_putc)(EOF);
+	return;
     } else if (c2 == 0) {
 	output_mode = ASCII;
-        (*o_putc)(c1);
-    } else if (c2 == JIS_X_0201) {
+	(*o_putc)(c1);
+    } else if (c2 == JIS_X_0201_1976_K) {
 	output_mode = SHIFT_JIS;
-        (*o_putc)(c1|0x80);
+	(*o_putc)(c1|0x80);
     } else if (c2 == ISO_8859_1) {
 	output_mode = ISO_8859_1;
-        (*o_putc)(c1 | 0x080);
+	(*o_putc)(c1 | 0x080);
 #ifdef X0212_ENABLE
     } else if (is_eucg3(c2)){
 	output_mode = SHIFT_JIS;
-        if (e2s_conv(c2, c1, &c2, &c1) == 0){
-            (*o_putc)(c2);
-            (*o_putc)(c1);
-        }
+	if (e2s_conv(c2, c1, &c2, &c1) == 0){
+	    (*o_putc)(c2);
+	    (*o_putc)(c1);
+	}
 #endif
     } else {
-        if (!nkf_isprint(c1) || !nkf_isprint(c2)) {
-            set_iconv(FALSE, 0);
-            return; /* too late to rescue this char */
-        }
+	if (!nkf_isprint(c1) || !nkf_isprint(c2)) {
+	    set_iconv(FALSE, 0);
+	    return; /* too late to rescue this char */
+	}
 	output_mode = SHIFT_JIS;
-        e2s_conv(c2, c1, &c2, &c1);
+	e2s_conv(c2, c1, &c2, &c1);
 
 #ifdef SHIFTJIS_CP932
-        if (cp932inv_f
-            && CP932INV_TABLE_BEGIN <= c2 && c2 <= CP932INV_TABLE_END){
-            nkf_char c = cp932inv[c2 - CP932INV_TABLE_BEGIN][c1 - 0x40];
-            if (c){
-                c2 = c >> 8;
-                c1 = c & 0xff;
-            }
-        }
+	if (cp932inv_f
+	    && CP932INV_TABLE_BEGIN <= c2 && c2 <= CP932INV_TABLE_END){
+	    nkf_char c = cp932inv[c2 - CP932INV_TABLE_BEGIN][c1 - 0x40];
+	    if (c){
+		c2 = c >> 8;
+		c1 = c & 0xff;
+	    }
+	}
 #endif /* SHIFTJIS_CP932 */
 
-        (*o_putc)(c2);
+	(*o_putc)(c2);
 	if (prefix_table[(unsigned char)c1]){
-            (*o_putc)(prefix_table[(unsigned char)c1]);
+	    (*o_putc)(prefix_table[(unsigned char)c1]);
 	}
-        (*o_putc)(c1);
+	(*o_putc)(c1);
     }
 }
 
 #ifdef UTF8_OUTPUT_ENABLE
-void w_oconv(nkf_char c2, nkf_char c1)
+static void
+w_oconv(nkf_char c2, nkf_char c1)
 {
-    nkf_char c0;
+    int c3, c4;
     nkf_char val;
 
     if (output_bom_f) {
 	output_bom_f = FALSE;
-    	(*o_putc)('\357');
+	(*o_putc)('\357');
 	(*o_putc)('\273');
 	(*o_putc)('\277');
     }
 
     if (c2 == EOF) {
-        (*o_putc)(EOF);
-        return;
+	(*o_putc)(EOF);
+	return;
     }
 
-#ifdef NUMCHAR_OPTION
-    if (c2 == 0 && is_unicode_capsule(c1)){
-        val = c1 & VALUE_MASK;
-        if (val < 0x80){
-            (*o_putc)(val);
-        }else if (val < 0x800){
-            (*o_putc)(0xC0 | (val >> 6));
-            (*o_putc)(0x80 | (val & 0x3f));
-        } else if (val <= NKF_INT32_C(0xFFFF)) {
-            (*o_putc)(0xE0 | (val >> 12));
-            (*o_putc)(0x80 | ((val >> 6) & 0x3f));
-            (*o_putc)(0x80 | (val        & 0x3f));
-        } else if (val <= NKF_INT32_C(0x10FFFF)) {
-            (*o_putc)(0xF0 | ( val>>18));
-            (*o_putc)(0x80 | ((val>>12) & 0x3f));
-            (*o_putc)(0x80 | ((val>> 6) & 0x3f));
-            (*o_putc)(0x80 | ( val      & 0x3f));
-        }
-        return;
+    if (c2 == 0 && nkf_char_unicode_p(c1)){
+	val = c1 & VALUE_MASK;
+	nkf_unicode_to_utf8(val, &c1, &c2, &c3, &c4);
+	(*o_putc)(c1);
+	if (c2) (*o_putc)(c2);
+	if (c3) (*o_putc)(c3);
+	if (c4) (*o_putc)(c4);
+	return;
     }
-#endif
 
     if (c2 == 0) {
-	output_mode = ASCII;
-        (*o_putc)(c1);
-    } else if (c2 == ISO_8859_1) {
-	output_mode = UTF_8;
-        (*o_putc)(c1 | 0x080);
+	(*o_putc)(c1);
     } else {
-        output_mode = UTF_8;
 	val = e2w_conv(c2, c1);
-        if (val){
-            w16w_conv(val, &c2, &c1, &c0);
-            (*o_putc)(c2);
-            if (c1){
-                (*o_putc)(c1);
-                if (c0) (*o_putc)(c0);
-            }
-        }
+	if (val){
+	    nkf_unicode_to_utf8(val, &c1, &c2, &c3, &c4);
+	    (*o_putc)(c1);
+	    if (c2) (*o_putc)(c2);
+	    if (c3) (*o_putc)(c3);
+	    if (c4) (*o_putc)(c4);
+	}
     }
 }
 
-void w_oconv16(nkf_char c2, nkf_char c1)
+static void
+w_oconv16(nkf_char c2, nkf_char c1)
 {
     if (output_bom_f) {
 	output_bom_f = FALSE;
-        if (output_endian == ENDIAN_LITTLE){
-            (*o_putc)((unsigned char)'\377');
-            (*o_putc)('\376');
-        }else{
-            (*o_putc)('\376');
-            (*o_putc)((unsigned char)'\377');
-        }
+	if (output_endian == ENDIAN_LITTLE){
+	    (*o_putc)(0xFF);
+	    (*o_putc)(0xFE);
+	}else{
+	    (*o_putc)(0xFE);
+	    (*o_putc)(0xFF);
+	}
     }
 
     if (c2 == EOF) {
-        (*o_putc)(EOF);
-        return;
+	(*o_putc)(EOF);
+	return;
     }
 
-    if (c2 == ISO_8859_1) {
-        c2 = 0;
-        c1 |= 0x80;
-#ifdef NUMCHAR_OPTION
-    } else if (c2 == 0 && is_unicode_capsule(c1)) {
-        if (is_unicode_bmp(c1)) {
-            c2 = (c1 >> 8) & 0xff;
-            c1 &= 0xff;
-        } else {
-            c1 &= VALUE_MASK;
-            if (c1 <= UNICODE_MAX) {
-                c2 = (c1 >> 10) + NKF_INT32_C(0xD7C0);   /* high surrogate */
-                c1 = (c1 & 0x3FF) + NKF_INT32_C(0xDC00); /* low surrogate */
-                if (output_endian == ENDIAN_LITTLE){
-                    (*o_putc)(c2 & 0xff);
-                    (*o_putc)((c2 >> 8) & 0xff);
-                    (*o_putc)(c1 & 0xff);
-                    (*o_putc)((c1 >> 8) & 0xff);
-                }else{
-                    (*o_putc)((c2 >> 8) & 0xff);
-                    (*o_putc)(c2 & 0xff);
-                    (*o_putc)((c1 >> 8) & 0xff);
-                    (*o_putc)(c1 & 0xff);
-                }
-            }
-            return;
-        }
-#endif
+    if (c2 == 0 && nkf_char_unicode_p(c1)) {
+	if (nkf_char_unicode_bmp_p(c1)) {
+	    c2 = (c1 >> 8) & 0xff;
+	    c1 &= 0xff;
+	} else {
+	    c1 &= VALUE_MASK;
+	    if (c1 <= UNICODE_MAX) {
+		c2 = (c1 >> 10) + NKF_INT32_C(0xD7C0);   /* high surrogate */
+		c1 = (c1 & 0x3FF) + NKF_INT32_C(0xDC00); /* low surrogate */
+		if (output_endian == ENDIAN_LITTLE){
+		    (*o_putc)(c2 & 0xff);
+		    (*o_putc)((c2 >> 8) & 0xff);
+		    (*o_putc)(c1 & 0xff);
+		    (*o_putc)((c1 >> 8) & 0xff);
+		}else{
+		    (*o_putc)((c2 >> 8) & 0xff);
+		    (*o_putc)(c2 & 0xff);
+		    (*o_putc)((c1 >> 8) & 0xff);
+		    (*o_putc)(c1 & 0xff);
+		}
+	    }
+	    return;
+	}
     } else if (c2) {
-        nkf_char val = e2w_conv(c2, c1);
-        c2 = (val >> 8) & 0xff;
-        c1 = val & 0xff;
+	nkf_char val = e2w_conv(c2, c1);
+	c2 = (val >> 8) & 0xff;
+	c1 = val & 0xff;
 	if (!val) return;
     }
     if (output_endian == ENDIAN_LITTLE){
-        (*o_putc)(c1);
-        (*o_putc)(c2);
+	(*o_putc)(c1);
+	(*o_putc)(c2);
     }else{
-        (*o_putc)(c2);
-        (*o_putc)(c1);
+	(*o_putc)(c2);
+	(*o_putc)(c1);
     }
 }
 
-void w_oconv32(nkf_char c2, nkf_char c1)
+static void
+w_oconv32(nkf_char c2, nkf_char c1)
 {
     if (output_bom_f) {
 	output_bom_f = FALSE;
-        if (output_endian == ENDIAN_LITTLE){
-            (*o_putc)((unsigned char)'\377');
-            (*o_putc)('\376');
-	    (*o_putc)('\000');
-	    (*o_putc)('\000');
-        }else{
-	    (*o_putc)('\000');
-	    (*o_putc)('\000');
-            (*o_putc)('\376');
-            (*o_putc)((unsigned char)'\377');
-        }
+	if (output_endian == ENDIAN_LITTLE){
+	    (*o_putc)(0xFF);
+	    (*o_putc)(0xFE);
+	    (*o_putc)(0);
+	    (*o_putc)(0);
+	}else{
+	    (*o_putc)(0);
+	    (*o_putc)(0);
+	    (*o_putc)(0xFE);
+	    (*o_putc)(0xFF);
+	}
     }
 
     if (c2 == EOF) {
-        (*o_putc)(EOF);
-        return;
+	(*o_putc)(EOF);
+	return;
     }
 
     if (c2 == ISO_8859_1) {
-        c1 |= 0x80;
-#ifdef NUMCHAR_OPTION
-    } else if (c2 == 0 && is_unicode_capsule(c1)) {
+	c1 |= 0x80;
+    } else if (c2 == 0 && nkf_char_unicode_p(c1)) {
 	c1 &= VALUE_MASK;
-#endif
     } else if (c2) {
-        c1 = e2w_conv(c2, c1);
+	c1 = e2w_conv(c2, c1);
 	if (!c1) return;
     }
     if (output_endian == ENDIAN_LITTLE){
-        (*o_putc)( c1 & NKF_INT32_C(0x000000FF));
-        (*o_putc)((c1 & NKF_INT32_C(0x0000FF00)) >>  8);
-        (*o_putc)((c1 & NKF_INT32_C(0x00FF0000)) >> 16);
-	(*o_putc)('\000');
+	(*o_putc)( c1        & 0xFF);
+	(*o_putc)((c1 >>  8) & 0xFF);
+	(*o_putc)((c1 >> 16) & 0xFF);
+	(*o_putc)(0);
     }else{
-	(*o_putc)('\000');
-        (*o_putc)((c1 & NKF_INT32_C(0x00FF0000)) >> 16);
-        (*o_putc)((c1 & NKF_INT32_C(0x0000FF00)) >>  8);
-        (*o_putc)( c1 & NKF_INT32_C(0x000000FF));
+	(*o_putc)(0);
+	(*o_putc)((c1 >> 16) & 0xFF);
+	(*o_putc)((c1 >>  8) & 0xFF);
+	(*o_putc)( c1        & 0xFF);
     }
 }
 #endif
@@ -2456,60 +2566,64 @@
 
 #define SCORE_INIT (SCORE_iMIME)
 
-static const unsigned char score_table_A0[] = {
+static const char score_table_A0[] = {
     0, 0, 0, 0,
     0, 0, 0, 0,
     0, SCORE_DEPEND, SCORE_DEPEND, SCORE_DEPEND,
     SCORE_DEPEND, SCORE_DEPEND, SCORE_DEPEND, SCORE_NO_EXIST,
 };
 
-static const unsigned char score_table_F0[] = {
+static const char score_table_F0[] = {
     SCORE_L2, SCORE_L2, SCORE_L2, SCORE_L2,
     SCORE_L2, SCORE_DEPEND, SCORE_NO_EXIST, SCORE_NO_EXIST,
     SCORE_DEPEND, SCORE_DEPEND, SCORE_CP932, SCORE_CP932,
     SCORE_CP932, SCORE_NO_EXIST, SCORE_NO_EXIST, SCORE_ERROR,
 };
 
-void set_code_score(struct input_code *ptr, nkf_char score)
+static void
+set_code_score(struct input_code *ptr, nkf_char score)
 {
     if (ptr){
-        ptr->score |= score;
+	ptr->score |= score;
     }
 }
 
-void clr_code_score(struct input_code *ptr, nkf_char score)
+static void
+clr_code_score(struct input_code *ptr, nkf_char score)
 {
     if (ptr){
-        ptr->score &= ~score;
+	ptr->score &= ~score;
     }
 }
 
-void code_score(struct input_code *ptr)
+static void
+code_score(struct input_code *ptr)
 {
     nkf_char c2 = ptr->buf[0];
 #ifdef UTF8_OUTPUT_ENABLE
     nkf_char c1 = ptr->buf[1];
 #endif
     if (c2 < 0){
-        set_code_score(ptr, SCORE_ERROR);
-    }else if (c2 == SSO){
-        set_code_score(ptr, SCORE_KANA);
+	set_code_score(ptr, SCORE_ERROR);
+    }else if (c2 == SS2){
+	set_code_score(ptr, SCORE_KANA);
     }else if (c2 == 0x8f){
-        set_code_score(ptr, SCORE_X0212);
+	set_code_score(ptr, SCORE_X0212);
 #ifdef UTF8_OUTPUT_ENABLE
     }else if (!e2w_conv(c2, c1)){
-        set_code_score(ptr, SCORE_NO_EXIST);
+	set_code_score(ptr, SCORE_NO_EXIST);
 #endif
     }else if ((c2 & 0x70) == 0x20){
-        set_code_score(ptr, score_table_A0[c2 & 0x0f]);
+	set_code_score(ptr, score_table_A0[c2 & 0x0f]);
     }else if ((c2 & 0x70) == 0x70){
-        set_code_score(ptr, score_table_F0[c2 & 0x0f]);
+	set_code_score(ptr, score_table_F0[c2 & 0x0f]);
     }else if ((c2 & 0x70) >= 0x50){
-        set_code_score(ptr, SCORE_L2);
+	set_code_score(ptr, SCORE_L2);
     }
 }
 
-void status_disable(struct input_code *ptr)
+static void
+status_disable(struct input_code *ptr)
 {
     ptr->stat = -1;
     ptr->buf[0] = -1;
@@ -2517,85 +2631,89 @@
     if (iconv == ptr->iconv_func) set_iconv(FALSE, 0);
 }
 
-void status_push_ch(struct input_code *ptr, nkf_char c)
+static void
+status_push_ch(struct input_code *ptr, nkf_char c)
 {
     ptr->buf[ptr->index++] = c;
 }
 
-void status_clear(struct input_code *ptr)
+static void
+status_clear(struct input_code *ptr)
 {
     ptr->stat = 0;
     ptr->index = 0;
 }
 
-void status_reset(struct input_code *ptr)
+static void
+status_reset(struct input_code *ptr)
 {
     status_clear(ptr);
     ptr->score = SCORE_INIT;
 }
 
-void status_reinit(struct input_code *ptr)
+static void
+status_reinit(struct input_code *ptr)
 {
     status_reset(ptr);
     ptr->_file_stat = 0;
 }
 
-void status_check(struct input_code *ptr, nkf_char c)
+static void
+status_check(struct input_code *ptr, nkf_char c)
 {
     if (c <= DEL && estab_f){
-        status_reset(ptr);
+	status_reset(ptr);
     }
 }
 
-void s_status(struct input_code *ptr, nkf_char c)
+static void
+s_status(struct input_code *ptr, nkf_char c)
 {
     switch(ptr->stat){
-      case -1:
-          status_check(ptr, c);
-          break;
-      case 0:
-          if (c <= DEL){
-              break;
-#ifdef NUMCHAR_OPTION
-          }else if (is_unicode_capsule(c)){
-              break;
-#endif
-          }else if (0xa1 <= c && c <= 0xdf){
-              status_push_ch(ptr, SSO);
-              status_push_ch(ptr, c);
-              code_score(ptr);
-              status_clear(ptr);
-          }else if ((0x81 <= c && c < 0xa0) || (0xe0 <= c && c <= 0xea)){
-              ptr->stat = 1;
-              status_push_ch(ptr, c);
-          }else if (0xed <= c && c <= 0xee){
-              ptr->stat = 3;
-              status_push_ch(ptr, c);
+    case -1:
+	status_check(ptr, c);
+	break;
+    case 0:
+	if (c <= DEL){
+	    break;
+	}else if (nkf_char_unicode_p(c)){
+	    break;
+	}else if (0xa1 <= c && c <= 0xdf){
+	    status_push_ch(ptr, SS2);
+	    status_push_ch(ptr, c);
+	    code_score(ptr);
+	    status_clear(ptr);
+	}else if ((0x81 <= c && c < 0xa0) || (0xe0 <= c && c <= 0xea)){
+	    ptr->stat = 1;
+	    status_push_ch(ptr, c);
+	}else if (0xed <= c && c <= 0xee){
+	    ptr->stat = 3;
+	    status_push_ch(ptr, c);
 #ifdef SHIFTJIS_CP932
-          }else if (is_ibmext_in_sjis(c)){
-              ptr->stat = 2;
-              status_push_ch(ptr, c);
+	}else if (is_ibmext_in_sjis(c)){
+	    ptr->stat = 2;
+	    status_push_ch(ptr, c);
 #endif /* SHIFTJIS_CP932 */
 #ifdef X0212_ENABLE
-          }else if (0xf0 <= c && c <= 0xfc){
-              ptr->stat = 1;
-              status_push_ch(ptr, c);
+	}else if (0xf0 <= c && c <= 0xfc){
+	    ptr->stat = 1;
+	    status_push_ch(ptr, c);
 #endif /* X0212_ENABLE */
-          }else{
-              status_disable(ptr);
-          }
-          break;
-      case 1:
-          if ((0x40 <= c && c <= 0x7e) || (0x80 <= c && c <= 0xfc)){
-              status_push_ch(ptr, c);
-              s2e_conv(ptr->buf[0], ptr->buf[1], &ptr->buf[0], &ptr->buf[1]);
-              code_score(ptr);
-              status_clear(ptr);
-          }else{
-              status_disable(ptr);
-          }
-          break;
-      case 2:
+	}else{
+	    status_disable(ptr);
+	}
+	break;
+    case 1:
+	if ((0x40 <= c && c <= 0x7e) || (0x80 <= c && c <= 0xfc)){
+	    status_push_ch(ptr, c);
+	    s2e_conv(ptr->buf[0], ptr->buf[1], &ptr->buf[0], &ptr->buf[1]);
+	    code_score(ptr);
+	    status_clear(ptr);
+	}else{
+	    status_disable(ptr);
+	}
+	break;
+    case 2:
 #ifdef SHIFTJIS_CP932
 	if ((0x40 <= c && c <= 0x7e) || (0x80 <= c && c <= 0xfc)) {
 	    status_push_ch(ptr, c);
@@ -2607,205 +2725,208 @@
 	}
 #endif /* SHIFTJIS_CP932 */
 	status_disable(ptr);
-          break;
-      case 3:
-          if ((0x40 <= c && c <= 0x7e) || (0x80 <= c && c <= 0xfc)){
-              status_push_ch(ptr, c);
-              s2e_conv(ptr->buf[0], ptr->buf[1], &ptr->buf[0], &ptr->buf[1]);
+	break;
+    case 3:
+	if ((0x40 <= c && c <= 0x7e) || (0x80 <= c && c <= 0xfc)){
+	    status_push_ch(ptr, c);
+	    s2e_conv(ptr->buf[0], ptr->buf[1], &ptr->buf[0], &ptr->buf[1]);
 	    set_code_score(ptr, SCORE_CP932);
 	    status_clear(ptr);
-          }else{
-              status_disable(ptr);
-          }
-          break;
+	}else{
+	    status_disable(ptr);
+	}
+	break;
     }
 }
 
-void e_status(struct input_code *ptr, nkf_char c)
+static void
+e_status(struct input_code *ptr, nkf_char c)
 {
     switch (ptr->stat){
-      case -1:
-          status_check(ptr, c);
-          break;
-      case 0:
-          if (c <= DEL){
-              break;
-#ifdef NUMCHAR_OPTION
-          }else if (is_unicode_capsule(c)){
-              break;
-#endif
-          }else if (SSO == c || (0xa1 <= c && c <= 0xfe)){
-              ptr->stat = 1;
-              status_push_ch(ptr, c);
+    case -1:
+	status_check(ptr, c);
+	break;
+    case 0:
+	if (c <= DEL){
+	    break;
+	}else if (nkf_char_unicode_p(c)){
+	    break;
+	}else if (SS2 == c || (0xa1 <= c && c <= 0xfe)){
+	    ptr->stat = 1;
+	    status_push_ch(ptr, c);
 #ifdef X0212_ENABLE
-          }else if (0x8f == c){
-              ptr->stat = 2;
-              status_push_ch(ptr, c);
+	}else if (0x8f == c){
+	    ptr->stat = 2;
+	    status_push_ch(ptr, c);
 #endif /* X0212_ENABLE */
-          }else{
-              status_disable(ptr);
-          }
-          break;
-      case 1:
-          if (0xa1 <= c && c <= 0xfe){
-              status_push_ch(ptr, c);
-              code_score(ptr);
-              status_clear(ptr);
-          }else{
-              status_disable(ptr);
-          }
-          break;
+	}else{
+	    status_disable(ptr);
+	}
+	break;
+    case 1:
+	if (0xa1 <= c && c <= 0xfe){
+	    status_push_ch(ptr, c);
+	    code_score(ptr);
+	    status_clear(ptr);
+	}else{
+	    status_disable(ptr);
+	}
+	break;
 #ifdef X0212_ENABLE
-      case 2:
-          if (0xa1 <= c && c <= 0xfe){
-              ptr->stat = 1;
-              status_push_ch(ptr, c);
-          }else{
-              status_disable(ptr);
-          }
+    case 2:
+	if (0xa1 <= c && c <= 0xfe){
+	    ptr->stat = 1;
+	    status_push_ch(ptr, c);
+	}else{
+	    status_disable(ptr);
+	}
 #endif /* X0212_ENABLE */
     }
 }
 
 #ifdef UTF8_INPUT_ENABLE
-void w_status(struct input_code *ptr, nkf_char c)
+static void
+w_status(struct input_code *ptr, nkf_char c)
 {
     switch (ptr->stat){
-      case -1:
-          status_check(ptr, c);
-          break;
-      case 0:
-          if (c <= DEL){
-              break;
-#ifdef NUMCHAR_OPTION
-          }else if (is_unicode_capsule(c)){
-              break;
-#endif
-          }else if (0xc0 <= c && c <= 0xdf){
-              ptr->stat = 1;
-              status_push_ch(ptr, c);
-          }else if (0xe0 <= c && c <= 0xef){
-              ptr->stat = 2;
-              status_push_ch(ptr, c);
-          }else if (0xf0 <= c && c <= 0xf4){
-              ptr->stat = 3;
-              status_push_ch(ptr, c);
-          }else{
-              status_disable(ptr);
-          }
-          break;
-      case 1:
-      case 2:
-          if (0x80 <= c && c <= 0xbf){
-              status_push_ch(ptr, c);
-              if (ptr->index > ptr->stat){
-                  int bom = (ptr->buf[0] == 0xef && ptr->buf[1] == 0xbb
-                             && ptr->buf[2] == 0xbf);
-                  w2e_conv(ptr->buf[0], ptr->buf[1], ptr->buf[2],
-                           &ptr->buf[0], &ptr->buf[1]);
-                  if (!bom){
-                      code_score(ptr);
-                  }
-                  status_clear(ptr);
-              }
-          }else{
-              status_disable(ptr);
-          }
-          break;
-      case 3:
+    case -1:
+	status_check(ptr, c);
+	break;
+    case 0:
+	if (c <= DEL){
+	    break;
+	}else if (nkf_char_unicode_p(c)){
+	    break;
+	}else if (0xc0 <= c && c <= 0xdf){
+	    ptr->stat = 1;
+	    status_push_ch(ptr, c);
+	}else if (0xe0 <= c && c <= 0xef){
+	    ptr->stat = 2;
+	    status_push_ch(ptr, c);
+	}else if (0xf0 <= c && c <= 0xf4){
+	    ptr->stat = 3;
+	    status_push_ch(ptr, c);
+	}else{
+	    status_disable(ptr);
+	}
+	break;
+    case 1:
+    case 2:
 	if (0x80 <= c && c <= 0xbf){
+	    status_push_ch(ptr, c);
+	    if (ptr->index > ptr->stat){
+		int bom = (ptr->buf[0] == 0xef && ptr->buf[1] == 0xbb
+			   && ptr->buf[2] == 0xbf);
+		w2e_conv(ptr->buf[0], ptr->buf[1], ptr->buf[2],
+			 &ptr->buf[0], &ptr->buf[1]);
+		if (!bom){
+		    code_score(ptr);
+		}
+		status_clear(ptr);
+	    }
+	}else{
+	    status_disable(ptr);
+	}
+	break;
+    case 3:
+	if (0x80 <= c && c <= 0xbf){
 	    if (ptr->index < ptr->stat){
 		status_push_ch(ptr, c);
 	    } else {
-	    	status_clear(ptr);
+		status_clear(ptr);
 	    }
-          }else{
-              status_disable(ptr);
-          }
-          break;
+	}else{
+	    status_disable(ptr);
+	}
+	break;
     }
 }
 #endif
 
-void code_status(nkf_char c)
+static void
+code_status(nkf_char c)
 {
     int action_flag = 1;
     struct input_code *result = 0;
     struct input_code *p = input_code_list;
     while (p->name){
-        if (!p->status_func) {
+	if (!p->status_func) {
 	    ++p;
 	    continue;
 	}
-        if (!p->status_func)
+	if (!p->status_func)
 	    continue;
-        (p->status_func)(p, c);
-        if (p->stat > 0){
-            action_flag = 0;
-        }else if(p->stat == 0){
-            if (result){
-                action_flag = 0;
-            }else{
-                result = p;
-            }
-        }
-        ++p;
+	(p->status_func)(p, c);
+	if (p->stat > 0){
+	    action_flag = 0;
+	}else if(p->stat == 0){
+	    if (result){
+		action_flag = 0;
+	    }else{
+		result = p;
+	    }
+	}
+	++p;
     }
 
     if (action_flag){
-        if (result && !estab_f){
-            set_iconv(TRUE, result->iconv_func);
-        }else if (c <= DEL){
-            struct input_code *ptr = input_code_list;
-            while (ptr->name){
-                status_reset(ptr);
-                ++ptr;
-            }
-        }
+	if (result && !estab_f){
+	    set_iconv(TRUE, result->iconv_func);
+	}else if (c <= DEL){
+	    struct input_code *ptr = input_code_list;
+	    while (ptr->name){
+		status_reset(ptr);
+		++ptr;
+	    }
+	}
     }
 }
 
 #ifndef WIN32DLL
-nkf_char std_getc(FILE *f)
+static nkf_char
+std_getc(FILE *f)
 {
     if (std_gc_ndx){
-        return std_gc_buf[--std_gc_ndx];
+	return std_gc_buf[--std_gc_ndx];
     }
     return getc(f);
 }
 #endif /*WIN32DLL*/
 
-nkf_char std_ungetc(nkf_char c, FILE *f)
+static nkf_char
+std_ungetc(nkf_char c, FILE *f)
 {
     if (std_gc_ndx == STD_GC_BUFSIZE){
-        return EOF;
+	return EOF;
     }
     std_gc_buf[std_gc_ndx++] = c;
     return c;
 }
 
 #ifndef WIN32DLL
-void std_putc(nkf_char c)
+static void
+std_putc(nkf_char c)
 {
     if(c!=EOF)
-      putchar(c);
+	putchar(c);
 }
 #endif /*WIN32DLL*/
 
 static unsigned char   hold_buf[HOLD_SIZE*2];
 static int             hold_count = 0;
-nkf_char push_hold_buf(nkf_char c2)
+static nkf_char
+push_hold_buf(nkf_char c2)
 {
     if (hold_count >= HOLD_SIZE*2)
-        return (EOF);
+	return (EOF);
     hold_buf[hold_count++] = (unsigned char)c2;
     return ((hold_count >= HOLD_SIZE*2) ? EOF : hold_count);
 }
 
-nkf_char
-h_conv(FILE *f, nkf_char c2, nkf_char c1)
+static int
+h_conv(FILE *f, int c1, int c2)
 {
-    nkf_char ret, c3, c0;
+    int ret, c4, c3;
     int hold_index;
 
 
@@ -2814,33 +2935,33 @@
     /** and it must be after 2 byte 8bit code            */
 
     hold_count = 0;
+    push_hold_buf(c1);
     push_hold_buf(c2);
-    push_hold_buf(c1);
 
-    while ((c1 = (*i_getc)(f)) != EOF) {
-        if (c1 == ESC){
-	    (*i_ungetc)(c1,f);
-            break;
-        }
-        code_status(c1);
-        if (push_hold_buf(c1) == EOF || estab_f){
-            break;
-        }
+    while ((c2 = (*i_getc)(f)) != EOF) {
+	if (c2 == ESC){
+	    (*i_ungetc)(c2,f);
+	    break;
+	}
+	code_status(c2);
+	if (push_hold_buf(c2) == EOF || estab_f) {
+	    break;
+	}
     }
 
-    if (!estab_f){
-        struct input_code *p = input_code_list;
-        struct input_code *result = p;
-        if (c1 == EOF){
-            code_status(c1);
-        }
-        while (p->name){
-            if (p->status_func && p->score < result->score){
-                result = p;
-            }
-            ++p;
-        }
-        set_iconv(TRUE, result->iconv_func);
+    if (!estab_f) {
+	struct input_code *p = input_code_list;
+	struct input_code *result = p;
+	if (c2 == EOF) {
+	    code_status(c2);
+	}
+	while (p->name) {
+	    if (p->status_func && p->score < result->score) {
+		result = p;
+	    }
+	    p++;
+	}
+	set_iconv(TRUE, result->iconv_func);
     }
 
 
@@ -2853,68 +2974,63 @@
      ** Kanji codes by oconv and leave estab_f unchanged.
      **/
 
-    ret = c1;
+    ret = c2;
     hold_index = 0;
     while (hold_index < hold_count){
-        c2 = hold_buf[hold_index++];
-        if (c2 <= DEL
-#ifdef NUMCHAR_OPTION
-            || is_unicode_capsule(c2)
-#endif
-            ){
-            (*iconv)(0, c2, 0);
-            continue;
-        }else if (iconv == s_iconv && 0xa1 <= c2 && c2 <= 0xdf){
-            (*iconv)(JIS_X_0201, c2, 0);
-            continue;
-        }
-        if (hold_index < hold_count){
-            c1 = hold_buf[hold_index++];
-        }else{
-            c1 = (*i_getc)(f);
-            if (c1 == EOF){
-                c3 = EOF;
-                break;
-            }
-            code_status(c1);
-        }
-        c0 = 0;
-        switch ((*iconv)(c2, c1, 0)) {  /* can be EUC/SJIS/UTF-8 */
+	c1 = hold_buf[hold_index++];
+	if (c1 <= DEL){
+	    (*iconv)(0, c1, 0);
+	    continue;
+	}else if (iconv == s_iconv && 0xa1 <= c1 && c1 <= 0xdf){
+	    (*iconv)(JIS_X_0201_1976_K, c1, 0);
+	    continue;
+	}
+	if (hold_index < hold_count){
+	    c2 = hold_buf[hold_index++];
+	}else{
+	    c2 = (*i_getc)(f);
+	    if (c2 == EOF){
+		c4 = EOF;
+		break;
+	    }
+	    code_status(c2);
+	}
+	c3 = 0;
+	switch ((*iconv)(c1, c2, 0)) {  /* can be EUC/SJIS/UTF-8 */
 	case -2:
 	    /* 4 bytes UTF-8 */
-            if (hold_index < hold_count){
-                c0 = hold_buf[hold_index++];
-            } else if ((c0 = (*i_getc)(f)) == EOF) {
+	    if (hold_index < hold_count){
+		c3 = hold_buf[hold_index++];
+	    } else if ((c3 = (*i_getc)(f)) == EOF) {
 		ret = EOF;
 		break;
 	    } else {
-                code_status(c0);
-		c0 <<= 8;
+		code_status(c3);
 		if (hold_index < hold_count){
-		    c3 = hold_buf[hold_index++];
-		} else if ((c3 = (*i_getc)(f)) == EOF) {
-		    c0 = ret = EOF;
+		    c4 = hold_buf[hold_index++];
+		} else if ((c4 = (*i_getc)(f)) == EOF) {
+		    c3 = ret = EOF;
 		    break;
 		} else {
-		    code_status(c3);
-		    (*iconv)(c2, c1, c0|c3);
+		    code_status(c4);
+		    (*iconv)(c1, c2, (c3<<8)|c4);
 		}
-            }
+	    }
 	    break;
 	case -1:
 	    /* 3 bytes EUC or UTF-8 */
-            if (hold_index < hold_count){
-                c0 = hold_buf[hold_index++];
-            } else if ((c0 = (*i_getc)(f)) == EOF) {
+	    if (hold_index < hold_count){
+		c3 = hold_buf[hold_index++];
+	    } else if ((c3 = (*i_getc)(f)) == EOF) {
 		ret = EOF;
 		break;
 	    } else {
-                code_status(c0);
-            }
-            (*iconv)(c2, c1, c0);
-            break;
+		code_status(c3);
+	    }
+	    (*iconv)(c1, c2, c3);
+	    break;
 	}
-	if (c0 == EOF) break;
+	if (c3 == EOF) break;
     }
     return ret;
 }
@@ -2922,7 +3038,8 @@
 /*
  * Check and Ignore BOM
  */
-void check_bom(FILE *f)
+static void
+check_bom(FILE *f)
 {
     int c2;
     switch(c2 = (*i_getc)(f)){
@@ -3036,22 +3153,26 @@
     nkf_char buf[3];
 } broken_state;
 
-static void init_broken_state(void)
+static void
+init_broken_state(void)
 {
     memset(&broken_state, 0, sizeof(broken_state));
 }
 
-static void push_broken_buf(nkf_char c)
+static void
+push_broken_buf(c)
 {
     broken_state.buf[broken_state.count++] = c;
 }
 
-static nkf_char pop_broken_buf(void)
+static nkf_char
+pop_broken_buf(void)
 {
     return broken_state.buf[--broken_state.count];
 }
 
-nkf_char broken_getc(FILE *f)
+static nkf_char
+broken_getc(FILE *f)
 {
     nkf_char c, c1;
 
@@ -3060,7 +3181,7 @@
     }
     c = (*i_bgetc)(f);
     if (c=='$' && broken_state.status != ESC
-            && (input_mode==ASCII || input_mode==JIS_X_0201)) {
+	&& (input_mode == ASCII || input_mode == JIS_X_0201_1976_K)) {
 	c1= (*i_bgetc)(f);
 	broken_state.status = 0;
 	if (c1=='@'|| c1=='B') {
@@ -3072,7 +3193,7 @@
 	    return c;
 	}
     } else if (c=='(' && broken_state.status != ESC
-            && (input_mode==JIS_X_0208 || input_mode==JIS_X_0201)) { /* ) */
+	       && (input_mode == JIS_X_0208 || input_mode == JIS_X_0201_1976_K)) {
 	c1= (*i_bgetc)(f);
 	broken_state.status = 0;
 	if (c1=='J'|| c1=='B') {
@@ -3089,14 +3210,16 @@
     }
 }
 
-nkf_char broken_ungetc(nkf_char c, FILE *f)
+static nkf_char
+broken_ungetc(nkf_char c, FILE *f)
 {
     if (broken_state.count < 2)
 	push_broken_buf(c);
     return c;
 }
 
-void eol_conv(nkf_char c2, nkf_char c1)
+static void
+eol_conv(nkf_char c2, nkf_char c1)
 {
     if (guess_f && input_eol != EOF) {
 	if (c2 == 0 && c1 == LF) {
@@ -3117,210 +3240,212 @@
 }
 
 /*
-  Return value of fold_conv()
+   Return value of fold_conv()
 
-       LF  add newline  and output char
-       CR  add newline  and output nothing
-       SP  space
-       0   skip
-       1   (or else) normal output
+   LF  add newline  and output char
+   CR  add newline  and output nothing
+   SP  space
+   0   skip
+   1   (or else) normal output
 
-  fold state in prev (previous character)
+   fold state in prev (previous character)
 
-      >0x80 Japanese (X0208/X0201)
-      <0x80 ASCII
-      LF    new line
-      SP    space
+   >0x80 Japanese (X0208/X0201)
+   <0x80 ASCII
+   LF    new line
+   SP    space
 
-  This fold algorthm does not preserve heading space in a line.
-  This is the main difference from fmt.
-*/
+   This fold algorthm does not preserve heading space in a line.
+   This is the main difference from fmt.
+ */
 
 #define char_size(c2,c1) (c2?2:1)
 
-void fold_conv(nkf_char c2, nkf_char c1)
+static void
+fold_conv(nkf_char c2, nkf_char c1)
 {
     nkf_char prev0;
     nkf_char fold_state;
 
     if (c1== CR && !fold_preserve_f) {
-    	fold_state=0;  /* ignore cr */
+	fold_state=0;  /* ignore cr */
     }else if (c1== LF&&f_prev==CR && fold_preserve_f) {
-        f_prev = LF;
-     	fold_state=0;  /* ignore cr */
+	f_prev = LF;
+	fold_state=0;  /* ignore cr */
     } else if (c1== BS) {
-        if (f_line>0) f_line--;
-        fold_state =  1;
+	if (f_line>0) f_line--;
+	fold_state =  1;
     } else if (c2==EOF && f_line != 0) {    /* close open last line */
-            fold_state = LF;
+	fold_state = LF;
     } else if ((c1==LF && !fold_preserve_f)
-               || ((c1==CR||(c1==LF&&f_prev!=CR))
-                   && fold_preserve_f)) {
-        /* new line */
-        if (fold_preserve_f) {
-            f_prev = c1;
-            f_line = 0;
-            fold_state =  CR;
+	       || ((c1==CR||(c1==LF&&f_prev!=CR))
+		   && fold_preserve_f)) {
+	/* new line */
+	if (fold_preserve_f) {
+	    f_prev = c1;
+	    f_line = 0;
+	    fold_state =  CR;
 	} else if ((f_prev == c1 && !fold_preserve_f)
-                   || (f_prev == LF && fold_preserve_f)
-                   ) {        /* duplicate newline */
-            if (f_line) {
-                f_line = 0;
-                fold_state =  LF;    /* output two newline */
-            } else {
-                f_line = 0;
-                fold_state =  1;
-            }
-        } else  {
-            if (f_prev&0x80) {     /* Japanese? */
-                f_prev = c1;
-                fold_state =  0;       /* ignore given single newline */
-            } else if (f_prev==SP) {
-                fold_state =  0;
-            } else {
-                f_prev = c1;
-                if (++f_line<=fold_len)
-                    fold_state =  SP;
-                else {
-                    f_line = 0;
-                    fold_state =  CR;        /* fold and output nothing */
-                }
-            }
-        }
+		   || (f_prev == LF && fold_preserve_f)
+		  ) {        /* duplicate newline */
+	    if (f_line) {
+		f_line = 0;
+		fold_state =  LF;    /* output two newline */
+	    } else {
+		f_line = 0;
+		fold_state =  1;
+	    }
+	} else  {
+	    if (f_prev&0x80) {     /* Japanese? */
+		f_prev = c1;
+		fold_state =  0;       /* ignore given single newline */
+	    } else if (f_prev==SP) {
+		fold_state =  0;
+	    } else {
+		f_prev = c1;
+		if (++f_line<=fold_len)
+		    fold_state =  SP;
+		else {
+		    f_line = 0;
+		    fold_state =  CR;        /* fold and output nothing */
+		}
+	    }
+	}
     } else if (c1=='\f') {
-        f_prev = LF;
-        f_line = 0;
-        fold_state =  LF;            /* output newline and clear */
+	f_prev = LF;
+	f_line = 0;
+	fold_state =  LF;            /* output newline and clear */
     } else if ( (c2==0  && c1==SP)||
-               (c2==0  && c1==TAB)||
-               (c2=='!'&& c1=='!')) {
-        /* X0208 kankaku or ascii space */
-            if (f_prev == SP) {
-                fold_state = 0;         /* remove duplicate spaces */
-            } else {
-                f_prev = SP;
-                if (++f_line<=fold_len)
-                    fold_state = SP;         /* output ASCII space only */
-                else {
-                    f_prev = SP; f_line = 0;
-                    fold_state = CR;        /* fold and output nothing */
-                }
-            }
+	       (c2==0  && c1==TAB)||
+	       (c2=='!'&& c1=='!')) {
+	/* X0208 kankaku or ascii space */
+	if (f_prev == SP) {
+	    fold_state = 0;         /* remove duplicate spaces */
+	} else {
+	    f_prev = SP;
+	    if (++f_line<=fold_len)
+		fold_state = SP;         /* output ASCII space only */
+	    else {
+		f_prev = SP; f_line = 0;
+		fold_state = CR;        /* fold and output nothing */
+	    }
+	}
     } else {
-        prev0 = f_prev; /* we still need this one... , but almost done */
-        f_prev = c1;
-        if (c2 || c2==JIS_X_0201)
-            f_prev |= 0x80;  /* this is Japanese */
-        f_line += char_size(c2,c1);
-        if (f_line<=fold_len) {   /* normal case */
-            fold_state = 1;
-        } else {
-            if (f_line>fold_len+fold_margin) { /* too many kinsoku suspension */
-                f_line = char_size(c2,c1);
-                fold_state =  LF;       /* We can't wait, do fold now */
-            } else if (c2==JIS_X_0201) {
-            /* simple kinsoku rules  return 1 means no folding  */
-                if (c1==(0xde&0x7f)) fold_state = 1; /* $B!+(B*/
-                else if (c1==(0xdf&0x7f)) fold_state = 1; /* $B!,(B*/
-                else if (c1==(0xa4&0x7f)) fold_state = 1; /* $B!#(B*/
-                else if (c1==(0xa3&0x7f)) fold_state = 1; /* $B!$(B*/
-                else if (c1==(0xa1&0x7f)) fold_state = 1; /* $B!W(B*/
-                else if (c1==(0xb0&0x7f)) fold_state = 1; /* - */
-                else if (SP<=c1 && c1<=(0xdf&0x7f)) {      /* X0201 */
+	prev0 = f_prev; /* we still need this one... , but almost done */
+	f_prev = c1;
+	if (c2 || c2 == JIS_X_0201_1976_K)
+	    f_prev |= 0x80;  /* this is Japanese */
+	f_line += char_size(c2,c1);
+	if (f_line<=fold_len) {   /* normal case */
+	    fold_state = 1;
+	} else {
+	    if (f_line>fold_len+fold_margin) { /* too many kinsoku suspension */
+		f_line = char_size(c2,c1);
+		fold_state =  LF;       /* We can't wait, do fold now */
+	    } else if (c2 == JIS_X_0201_1976_K) {
+		/* simple kinsoku rules  return 1 means no folding  */
+		if (c1==(0xde&0x7f)) fold_state = 1; /* $B!+(B*/
+		else if (c1==(0xdf&0x7f)) fold_state = 1; /* $B!,(B*/
+		else if (c1==(0xa4&0x7f)) fold_state = 1; /* $B!#(B*/
+		else if (c1==(0xa3&0x7f)) fold_state = 1; /* $B!$(B*/
+		else if (c1==(0xa1&0x7f)) fold_state = 1; /* $B!W(B*/
+		else if (c1==(0xb0&0x7f)) fold_state = 1; /* - */
+		else if (SP<=c1 && c1<=(0xdf&0x7f)) {      /* X0201 */
 		    f_line = 1;
 		    fold_state = LF;/* add one new f_line before this character */
 		} else {
 		    f_line = 1;
 		    fold_state = LF;/* add one new f_line before this character */
 		}
-            } else if (c2==0) {
-                /* kinsoku point in ASCII */
+	    } else if (c2==0) {
+		/* kinsoku point in ASCII */
 		if (  c1==')'||    /* { [ ( */
-                     c1==']'||
-                     c1=='}'||
-                     c1=='.'||
-                     c1==','||
-                     c1=='!'||
-                     c1=='?'||
-                     c1=='/'||
-                     c1==':'||
-                     c1==';') {
+		    c1==']'||
+		    c1=='}'||
+		    c1=='.'||
+		    c1==','||
+		    c1=='!'||
+		    c1=='?'||
+		    c1=='/'||
+		    c1==':'||
+		    c1==';') {
 		    fold_state = 1;
-		/* just after special */
+		    /* just after special */
 		} else if (!is_alnum(prev0)) {
 		    f_line = char_size(c2,c1);
 		    fold_state = LF;
 		} else if ((prev0==SP) ||   /* ignored new f_line */
-                      (prev0==LF)||        /* ignored new f_line */
-                      (prev0&0x80)) {        /* X0208 - ASCII */
+			   (prev0==LF)||        /* ignored new f_line */
+			   (prev0&0x80)) {        /* X0208 - ASCII */
 		    f_line = char_size(c2,c1);
-                    fold_state = LF;/* add one new f_line before this character */
-                } else {
-                    fold_state = 1;  /* default no fold in ASCII */
-                }
-            } else {
-                if (c2=='!') {
-                    if (c1=='"')  fold_state = 1; /* $B!"(B */
-                    else if (c1=='#')  fold_state = 1; /* $B!#(B */
-                    else if (c1=='W')  fold_state = 1; /* $B!W(B */
-                    else if (c1=='K')  fold_state = 1; /* $B!K(B */
-                    else if (c1=='$')  fold_state = 1; /* $B!$(B */
-                    else if (c1=='%')  fold_state = 1; /* $B!%(B */
-                    else if (c1=='\'') fold_state = 1; /* $B!\(B */
-                    else if (c1=='(')  fold_state = 1; /* $B!((B */
-                    else if (c1==')')  fold_state = 1; /* $B!)(B */
-                    else if (c1=='*')  fold_state = 1; /* $B!*(B */
-                    else if (c1=='+')  fold_state = 1; /* $B!+(B */
-                    else if (c1==',')  fold_state = 1; /* $B!,(B */
-                         /* default no fold in kinsoku */
+		    fold_state = LF;/* add one new f_line before this character */
+		} else {
+		    fold_state = 1;  /* default no fold in ASCII */
+		}
+	    } else {
+		if (c2=='!') {
+		    if (c1=='"')  fold_state = 1; /* $B!"(B */
+		    else if (c1=='#')  fold_state = 1; /* $B!#(B */
+		    else if (c1=='W')  fold_state = 1; /* $B!W(B */
+		    else if (c1=='K')  fold_state = 1; /* $B!K(B */
+		    else if (c1=='$')  fold_state = 1; /* $B!$(B */
+		    else if (c1=='%')  fold_state = 1; /* $B!%(B */
+		    else if (c1=='\'') fold_state = 1; /* $B!\(B */
+		    else if (c1=='(')  fold_state = 1; /* $B!((B */
+		    else if (c1==')')  fold_state = 1; /* $B!)(B */
+		    else if (c1=='*')  fold_state = 1; /* $B!*(B */
+		    else if (c1=='+')  fold_state = 1; /* $B!+(B */
+		    else if (c1==',')  fold_state = 1; /* $B!,(B */
+		    /* default no fold in kinsoku */
 		    else {
 			fold_state = LF;
 			f_line = char_size(c2,c1);
 			/* add one new f_line before this character */
 		    }
-                } else {
+		} else {
 		    f_line = char_size(c2,c1);
-                    fold_state = LF;
-                    /* add one new f_line before this character */
-                }
-            }
-        }
+		    fold_state = LF;
+		    /* add one new f_line before this character */
+		}
+	    }
+	}
     }
     /* terminator process */
     switch(fold_state) {
-        case LF:
-            OCONV_NEWLINE((*o_fconv));
-            (*o_fconv)(c2,c1);
-            break;
-        case 0:
-            return;
-        case CR:
-            OCONV_NEWLINE((*o_fconv));
-            break;
-        case TAB:
-        case SP:
-            (*o_fconv)(0,SP);
-            break;
-        default:
-            (*o_fconv)(c2,c1);
+    case LF:
+	OCONV_NEWLINE((*o_fconv));
+	(*o_fconv)(c2,c1);
+	break;
+    case 0:
+	return;
+    case CR:
+	OCONV_NEWLINE((*o_fconv));
+	break;
+    case TAB:
+    case SP:
+	(*o_fconv)(0,SP);
+	break;
+    default:
+	(*o_fconv)(c2,c1);
     }
 }
 
-nkf_char z_prev2=0,z_prev1=0;
+static nkf_char z_prev2=0,z_prev1=0;
 
-void z_conv(nkf_char c2, nkf_char c1)
+static void
+z_conv(nkf_char c2, nkf_char c1)
 {
 
     /* if (c2) c1 &= 0x7f; assertion */
 
-    if (c2 == JIS_X_0201 && (c1 == 0x20 || c1 == 0x7D || c1 == 0x7E)) {
+    if (c2 == JIS_X_0201_1976_K && (c1 == 0x20 || c1 == 0x7D || c1 == 0x7E)) {
 	(*o_zconv)(c2,c1);
 	return;
     }
 
     if (x0201_f) {
-	if (z_prev2 == JIS_X_0201) {
-	    if (c2 == JIS_X_0201) {
+	if (z_prev2 == JIS_X_0201_1976_K) {
+	    if (c2 == JIS_X_0201_1976_K) {
 		if (c1 == (0xde&0x7f)) { /* $BByE@(B */
 		    z_prev2 = 0;
 		    (*o_zconv)(dv[(z_prev1-SP)*2], dv[(z_prev1-SP)*2+1]);
@@ -3334,7 +3459,7 @@
 	    z_prev2 = 0;
 	    (*o_zconv)(cv[(z_prev1-SP)*2], cv[(z_prev1-SP)*2+1]);
 	}
-	if (c2 == JIS_X_0201) {
+	if (c2 == JIS_X_0201_1976_K) {
 	    if (dv[(c1-SP)*2] || ev[(c1-SP)*2]) {
 		/* wait for $BByE@(B or $BH>ByE@(B */
 		z_prev1 = c1;
@@ -3348,28 +3473,28 @@
     }
 
     if (c2 == EOF) {
-        (*o_zconv)(c2, c1);
-        return;
+	(*o_zconv)(c2, c1);
+	return;
     }
 
     if (alpha_f&1 && c2 == 0x23) {
 	/* JISX0208 Alphabet */
-        c2 = 0;
+	c2 = 0;
     } else if (c2 == 0x21) {
 	/* JISX0208 Kigou */
-       if (0x21==c1) {
-           if (alpha_f&2) {
-               c2 = 0;
-               c1 = SP;
-           } else if (alpha_f&4) {
-                (*o_zconv)(0, SP);
-                (*o_zconv)(0, SP);
-                return;
-           }
-       } else if (alpha_f&1 && 0x20<c1 && c1<0x7f && fv[c1-0x20]) {
-           c2 =  0;
-           c1 = fv[c1-0x20];
-       }
+	if (0x21==c1) {
+	    if (alpha_f&2) {
+		c2 = 0;
+		c1 = SP;
+	    } else if (alpha_f&4) {
+		(*o_zconv)(0, SP);
+		(*o_zconv)(0, SP);
+		return;
+	    }
+	} else if (alpha_f&1 && 0x20<c1 && c1<0x7f && fv[c1-0x20]) {
+	    c2 =  0;
+	    c1 = fv[c1-0x20];
+	}
     }
 
     if (alpha_f&8 && c2 == 0) {
@@ -3390,7 +3515,7 @@
     if (alpha_f & 16) {
 	/* JIS X 0208 Katakana to JIS X 0201 Katakana */
 	if (c2 == 0x21) {
-	    nkf_char c = 0;
+	    char c = 0;
 	    switch (c1) {
 	    case 0x23:
 		/* U+3002 (0x8142) Ideographic Full Stop -> U+FF61 (0xA1) Halfwidth Ideographic Full Stop */
@@ -3426,7 +3551,7 @@
 		break;
 	    }
 	    if (c) {
-		(*o_zconv)(JIS_X_0201, c);
+		(*o_zconv)(JIS_X_0201_1976_K, c);
 		return;
 	    }
 	} else if (c2 == 0x25) {
@@ -3448,9 +3573,9 @@
 	    };
 	    if (fullwidth_to_halfwidth[c1-0x20]){
 		c2 = fullwidth_to_halfwidth[c1-0x20];
-		(*o_zconv)(JIS_X_0201, c2>>8);
+		(*o_zconv)(JIS_X_0201_1976_K, c2>>8);
 		if (c2 & 0xFF) {
-		    (*o_zconv)(JIS_X_0201, c2&0xFF);
+		    (*o_zconv)(JIS_X_0201_1976_K, c2&0xFF);
 		}
 		return;
 	    }
@@ -3461,25 +3586,26 @@
 
 
 #define rot13(c)  ( \
-      ( c < 'A') ? c: \
-      (c <= 'M')  ? (c + 13): \
-      (c <= 'Z')  ? (c - 13): \
-      (c < 'a')   ? (c): \
-      (c <= 'm')  ? (c + 13): \
-      (c <= 'z')  ? (c - 13): \
-      (c) \
-)
+		   ( c < 'A') ? c: \
+		   (c <= 'M')  ? (c + 13): \
+		   (c <= 'Z')  ? (c - 13): \
+		   (c < 'a')   ? (c): \
+		   (c <= 'm')  ? (c + 13): \
+		   (c <= 'z')  ? (c - 13): \
+		   (c) \
+		  )
 
 #define  rot47(c) ( \
-      ( c < '!') ? c: \
-      ( c <= 'O') ? (c + 47) : \
-      ( c <= '~') ?  (c - 47) : \
-      c \
-)
+		   ( c < '!') ? c: \
+		   ( c <= 'O') ? (c + 47) : \
+		   ( c <= '~') ?  (c - 47) : \
+		   c \
+		  )
 
-void rot_conv(nkf_char c2, nkf_char c1)
+static void
+rot_conv(nkf_char c2, nkf_char c1)
 {
-    if (c2==0 || c2==JIS_X_0201 || c2==ISO_8859_1) {
+    if (c2 == 0 || c2 == JIS_X_0201_1976_K || c2 == ISO_8859_1) {
 	c1 = rot13(c1);
     } else if (c2) {
 	c1 = rot47(c1);
@@ -3488,62 +3614,64 @@
     (*o_rot_conv)(c2,c1);
 }
 
-void hira_conv(nkf_char c2, nkf_char c1)
+static void
+hira_conv(nkf_char c2, nkf_char c1)
 {
     if (hira_f & 1) {
-        if (c2 == 0x25) {
-            if (0x20 < c1 && c1 < 0x74) {
-                c2 = 0x24;
-                (*o_hira_conv)(c2,c1);
-                return;
-            } else if (c1 == 0x74 && nkf_enc_unicode_p(output_encoding)) {
-                c2 = 0;
-                c1 = CLASS_UNICODE | 0x3094;
-                (*o_hira_conv)(c2,c1);
-                return;
-            }
-        } else if (c2 == 0x21 && (c1 == 0x33 || c1 == 0x34)) {
-            c1 += 2;
-            (*o_hira_conv)(c2,c1);
-            return;
-        }
+	if (c2 == 0x25) {
+	    if (0x20 < c1 && c1 < 0x74) {
+		c2 = 0x24;
+		(*o_hira_conv)(c2,c1);
+		return;
+	    } else if (c1 == 0x74 && nkf_enc_unicode_p(output_encoding)) {
+		c2 = 0;
+		c1 = nkf_char_unicode_new(0x3094);
+		(*o_hira_conv)(c2,c1);
+		return;
+	    }
+	} else if (c2 == 0x21 && (c1 == 0x33 || c1 == 0x34)) {
+	    c1 += 2;
+	    (*o_hira_conv)(c2,c1);
+	    return;
+	}
     }
     if (hira_f & 2) {
-        if (c2 == 0 && c1 == (CLASS_UNICODE | 0x3094)) {
-            c2 = 0x25;
-            c1 = 0x74;
-        } else if (c2 == 0x24 && 0x20 < c1 && c1 < 0x74) {
-            c2 = 0x25;
-        } else if (c2 == 0x21 && (c1 == 0x35 || c1 == 0x36)) {
-            c1 -= 2;
-        }
+	if (c2 == 0 && c1 == nkf_char_unicode_new(0x3094)) {
+	    c2 = 0x25;
+	    c1 = 0x74;
+	} else if (c2 == 0x24 && 0x20 < c1 && c1 < 0x74) {
+	    c2 = 0x25;
+	} else if (c2 == 0x21 && (c1 == 0x35 || c1 == 0x36)) {
+	    c1 -= 2;
+	}
     }
     (*o_hira_conv)(c2,c1);
 }
 
 
-void iso2022jp_check_conv(nkf_char c2, nkf_char c1)
+static void
+iso2022jp_check_conv(nkf_char c2, nkf_char c1)
 {
 #define RANGE_NUM_MAX 18
     static const nkf_char range[RANGE_NUM_MAX][2] = {
-        {0x222f, 0x2239,},
-        {0x2242, 0x2249,},
-        {0x2251, 0x225b,},
-        {0x226b, 0x2271,},
-        {0x227a, 0x227d,},
-        {0x2321, 0x232f,},
-        {0x233a, 0x2340,},
-        {0x235b, 0x2360,},
-        {0x237b, 0x237e,},
-        {0x2474, 0x247e,},
-        {0x2577, 0x257e,},
-        {0x2639, 0x2640,},
-        {0x2659, 0x267e,},
-        {0x2742, 0x2750,},
-        {0x2772, 0x277e,},
-        {0x2841, 0x287e,},
-        {0x4f54, 0x4f7e,},
-        {0x7425, 0x747e},
+	{0x222f, 0x2239,},
+	{0x2242, 0x2249,},
+	{0x2251, 0x225b,},
+	{0x226b, 0x2271,},
+	{0x227a, 0x227d,},
+	{0x2321, 0x232f,},
+	{0x233a, 0x2340,},
+	{0x235b, 0x2360,},
+	{0x237b, 0x237e,},
+	{0x2474, 0x247e,},
+	{0x2577, 0x257e,},
+	{0x2639, 0x2640,},
+	{0x2659, 0x267e,},
+	{0x2742, 0x2750,},
+	{0x2772, 0x277e,},
+	{0x2841, 0x287e,},
+	{0x4f54, 0x4f7e,},
+	{0x7425, 0x747e},
     };
     nkf_char i;
     nkf_char start, end, c;
@@ -3598,7 +3726,7 @@
 };
 
 static const nkf_char mime_encode[] = {
-    EUC_JP, SHIFT_JIS, ISO_8859_1, ISO_8859_1, JIS_X_0208, JIS_X_0201,
+    EUC_JP, SHIFT_JIS, ISO_8859_1, ISO_8859_1, JIS_X_0208, JIS_X_0201_1976_K,
 #if defined(UTF8_INPUT_ENABLE)
     UTF_8, UTF_8,
 #endif
@@ -3631,18 +3759,21 @@
 
 #define MAXRECOVER 20
 
-static void mime_input_buf_unshift(nkf_char c)
+static void
+mime_input_buf_unshift(nkf_char c)
 {
     mime_input_buf(--mime_input_state.top) = (unsigned char)c;
 }
 
-nkf_char mime_ungetc(nkf_char c, FILE *f)
+static nkf_char
+mime_ungetc(nkf_char c, FILE *f)
 {
     mime_input_buf_unshift(c);
     return c;
 }
 
-nkf_char mime_ungetc_buf(nkf_char c, FILE *f)
+static nkf_char
+mime_ungetc_buf(nkf_char c, FILE *f)
 {
     if (mimebuf_f)
 	(*i_mungetc_buf)(c,f);
@@ -3651,15 +3782,17 @@
     return c;
 }
 
-nkf_char mime_getc_buf(FILE *f)
+static nkf_char
+mime_getc_buf(FILE *f)
 {
     /* we don't keep eof of mime_input_buf, becase it contains ?= as
        a terminator. It was checked in mime_integrity. */
     return ((mimebuf_f)?
-        (*i_mgetc_buf)(f):mime_input_buf(mime_input_state.input++));
+	    (*i_mgetc_buf)(f):mime_input_buf(mime_input_state.input++));
 }
 
-void switch_mime_getc(void)
+static void
+switch_mime_getc(void)
 {
     if (i_getc!=mime_getc) {
 	i_mgetc = i_getc; i_getc = mime_getc;
@@ -3671,7 +3804,8 @@
     }
 }
 
-void unswitch_mime_getc(void)
+static void
+unswitch_mime_getc(void)
 {
     if(mime_f==STRICT_MIME) {
 	i_mgetc = i_mgetc_buf;
@@ -3683,7 +3817,8 @@
     mime_iconv_back = NULL;
 }
 
-nkf_char mime_integrity(FILE *f, const unsigned char *p)
+static nkf_char
+mime_integrity(FILE *f, const unsigned char *p)
 {
     nkf_char c,d;
     unsigned int q;
@@ -3696,22 +3831,22 @@
     d = 0;
     q = mime_input_state.input;
     while((c=(*i_getc)(f))!=EOF) {
-        if (((mime_input_state.input-mime_input_state.top)&MIME_BUF_MASK)==0) {
+	if (((mime_input_state.input-mime_input_state.top)&MIME_BUF_MASK)==0) {
 	    break;   /* buffer full */
 	}
-        if (c=='=' && d=='?') {
-            /* checked. skip header, start decode */
-            mime_input_buf(mime_input_state.input++) = (unsigned char)c;
-            /* mime_last_input = mime_input_state.input; */
-            mime_input_state.input = q;
+	if (c=='=' && d=='?') {
+	    /* checked. skip header, start decode */
+	    mime_input_buf(mime_input_state.input++) = (unsigned char)c;
+	    /* mime_last_input = mime_input_state.input; */
+	    mime_input_state.input = q;
 	    switch_mime_getc();
-            return 1;
-        }
-        if (!( (c=='+'||c=='/'|| c=='=' || c=='?' || is_alnum(c))))
-            break;
-        /* Should we check length mod 4? */
-        mime_input_buf(mime_input_state.input++) = (unsigned char)c;
-        d=c;
+	    return 1;
+	}
+	if (!( (c=='+'||c=='/'|| c=='=' || c=='?' || is_alnum(c))))
+	    break;
+	/* Should we check length mod 4? */
+	mime_input_buf(mime_input_state.input++) = (unsigned char)c;
+	d=c;
     }
     /* In case of Incomplete MIME, no MIME decode  */
     mime_input_buf(mime_input_state.input++) = (unsigned char)c;
@@ -3721,7 +3856,8 @@
     return 1;
 }
 
-nkf_char mime_begin_strict(FILE *f)
+static nkf_char
+mime_begin_strict(FILE *f)
 {
     nkf_char c1 = 0;
     int i,j,k;
@@ -3735,24 +3871,24 @@
     r[0]='='; r[1]='?';
 
     for(i=2;p[i]>SP;i++) {                   /* start at =? */
-        if (((r[i] = c1 = (*i_getc)(f))==EOF) || nkf_toupper(c1) != p[i]) {
-            /* pattern fails, try next one */
-            q = p;
-            while (mime_pattern[++j]) {
+	if (((r[i] = c1 = (*i_getc)(f))==EOF) || nkf_toupper(c1) != p[i]) {
+	    /* pattern fails, try next one */
+	    q = p;
+	    while (mime_pattern[++j]) {
 		p = mime_pattern[j];
-                for(k=2;k<i;k++)              /* assume length(p) > i */
-                    if (p[k]!=q[k]) break;
-                if (k==i && nkf_toupper(c1)==p[k]) break;
-            }
+		for(k=2;k<i;k++)              /* assume length(p) > i */
+		    if (p[k]!=q[k]) break;
+		if (k==i && nkf_toupper(c1)==p[k]) break;
+	    }
 	    p = mime_pattern[j];
-            if (p) continue;  /* found next one, continue */
-            /* all fails, output from recovery buffer */
-            (*i_ungetc)(c1,f);
-            for(j=0;j<i;j++) {
-                (*oconv)(0,r[j]);
-            }
-            return c1;
-        }
+	    if (p) continue;  /* found next one, continue */
+	    /* all fails, output from recovery buffer */
+	    (*i_ungetc)(c1,f);
+	    for(j=0;j<i;j++) {
+		(*oconv)(0,r[j]);
+	    }
+	    return c1;
+	}
     }
     mime_decode_mode = p[i-2];
 
@@ -3761,18 +3897,19 @@
     clr_code_score(find_inputcode_byfunc(mime_priority_func[j]), SCORE_iMIME);
 
     if (mime_decode_mode=='B') {
-        mimebuf_f = unbuf_f;
-        if (!unbuf_f) {
-            /* do MIME integrity check */
-            return mime_integrity(f,mime_pattern[j]);
-        }
+	mimebuf_f = unbuf_f;
+	if (!unbuf_f) {
+	    /* do MIME integrity check */
+	    return mime_integrity(f,mime_pattern[j]);
+	}
     }
     switch_mime_getc();
     mimebuf_f = TRUE;
     return c1;
 }
 
-nkf_char mime_begin(FILE *f)
+static nkf_char
+mime_begin(FILE *f)
 {
     nkf_char c1;
     int i,k;
@@ -3784,43 +3921,43 @@
     k = mime_input_state.last;
     mime_input_buf(mime_input_state.last++)='='; mime_input_buf(mime_input_state.last++)='?';
     for(i=2;i<MAXRECOVER;i++) {                   /* start at =? */
-        /* We accept any character type even if it is breaked by new lines */
-        c1 = (*i_getc)(f); mime_input_buf(mime_input_state.last++) = (unsigned char)c1;
-        if (c1==LF||c1==SP||c1==CR||
-                c1=='-'||c1=='_'||is_alnum(c1)) continue;
-        if (c1=='=') {
-            /* Failed. But this could be another MIME preemble */
-            (*i_ungetc)(c1,f);
-            mime_input_state.last--;
-            break;
-        }
-        if (c1!='?') break;
-        else {
-            /* c1=='?' */
-            c1 = (*i_getc)(f); mime_input_buf(mime_input_state.last++) = (unsigned char)c1;
-            if (!(++i<MAXRECOVER) || c1==EOF) break;
-            if (c1=='b'||c1=='B') {
-                mime_decode_mode = 'B';
-            } else if (c1=='q'||c1=='Q') {
-                mime_decode_mode = 'Q';
-            } else {
-                break;
-            }
-            c1 = (*i_getc)(f); mime_input_buf(mime_input_state.last++) = (unsigned char)c1;
-            if (!(++i<MAXRECOVER) || c1==EOF) break;
-            if (c1!='?') {
-                mime_decode_mode = FALSE;
-            }
-            break;
-        }
+	/* We accept any character type even if it is breaked by new lines */
+	c1 = (*i_getc)(f); mime_input_buf(mime_input_state.last++) = (unsigned char)c1;
+	if (c1==LF||c1==SP||c1==CR||
+	    c1=='-'||c1=='_'||is_alnum(c1)) continue;
+	if (c1=='=') {
+	    /* Failed. But this could be another MIME preemble */
+	    (*i_ungetc)(c1,f);
+	    mime_input_state.last--;
+	    break;
+	}
+	if (c1!='?') break;
+	else {
+	    /* c1=='?' */
+	    c1 = (*i_getc)(f); mime_input_buf(mime_input_state.last++) = (unsigned char)c1;
+	    if (!(++i<MAXRECOVER) || c1==EOF) break;
+	    if (c1=='b'||c1=='B') {
+		mime_decode_mode = 'B';
+	    } else if (c1=='q'||c1=='Q') {
+		mime_decode_mode = 'Q';
+	    } else {
+		break;
+	    }
+	    c1 = (*i_getc)(f); mime_input_buf(mime_input_state.last++) = (unsigned char)c1;
+	    if (!(++i<MAXRECOVER) || c1==EOF) break;
+	    if (c1!='?') {
+		mime_decode_mode = FALSE;
+	    }
+	    break;
+	}
     }
     switch_mime_getc();
     if (!mime_decode_mode) {
-        /* false MIME premble, restart from mime_buffer */
-        mime_decode_mode = 1;  /* no decode, but read from the mime_buffer */
-        /* Since we are in MIME mode until buffer becomes empty,    */
-        /* we never go into mime_begin again for a while.           */
-        return c1;
+	/* false MIME premble, restart from mime_buffer */
+	mime_decode_mode = 1;  /* no decode, but read from the mime_buffer */
+	/* Since we are in MIME mode until buffer becomes empty,    */
+	/* we never go into mime_begin again for a while.           */
+	return c1;
     }
     /* discard mime preemble, and goto MIME mode */
     mime_input_state.last = k;
@@ -3829,20 +3966,23 @@
 }
 
 #ifdef CHECK_OPTION
-void no_putc(nkf_char c)
+static void
+no_putc(nkf_char c)
 {
     ;
 }
 
-void debug(const char *str)
+static void
+debug(const char *str)
 {
     if (debug_f){
-        fprintf(stderr, "%s\n", str ? str : "NULL");
+	fprintf(stderr, "%s\n", str ? str : "NULL");
     }
 }
 #endif
 
-void set_input_codename(char *codename)
+static void
+set_input_codename(char *codename)
 {
     if (!input_codename) {
 	input_codename = codename;
@@ -3851,7 +3991,8 @@
     }
 }
 
-static char* get_guessed_code(void)
+static char*
+get_guessed_code(void)
 {
     if (input_codename && !*input_codename) {
 	input_codename = "BINARY";
@@ -3878,7 +4019,8 @@
 }
 
 #if !defined(PERL_XS) && !defined(WIN32DLL)
-void print_guessed_code(char *filename)
+static void
+print_guessed_code(char *filename)
 {
     if (filename != NULL) printf("%s: ", filename);
     if (input_codename && !*input_codename) {
@@ -3902,50 +4044,56 @@
 
 #ifdef INPUT_OPTION
 
-nkf_char hex_getc(nkf_char ch, FILE *f, nkf_char (*g)(FILE *f), nkf_char (*u)(nkf_char c, FILE *f))
+static nkf_char
+hex_getc(nkf_char ch, FILE *f, nkf_char (*g)(FILE *f), nkf_char (*u)(nkf_char c, FILE *f))
 {
     nkf_char c1, c2, c3;
     c1 = (*g)(f);
     if (c1 != ch){
-        return c1;
+	return c1;
     }
     c2 = (*g)(f);
     if (!nkf_isxdigit(c2)){
-        (*u)(c2, f);
-        return c1;
+	(*u)(c2, f);
+	return c1;
     }
     c3 = (*g)(f);
     if (!nkf_isxdigit(c3)){
-        (*u)(c2, f);
-        (*u)(c3, f);
-        return c1;
+	(*u)(c2, f);
+	(*u)(c3, f);
+	return c1;
     }
     return (hex2bin(c2) << 4) | hex2bin(c3);
 }
 
-nkf_char cap_getc(FILE *f)
+static nkf_char
+cap_getc(FILE *f)
 {
     return hex_getc(':', f, i_cgetc, i_cungetc);
 }
 
-nkf_char cap_ungetc(nkf_char c, FILE *f)
+static nkf_char
+cap_ungetc(nkf_char c, FILE *f)
 {
     return (*i_cungetc)(c, f);
 }
 
-nkf_char url_getc(FILE *f)
+static nkf_char
+url_getc(FILE *f)
 {
     return hex_getc('%', f, i_ugetc, i_uungetc);
 }
 
-nkf_char url_ungetc(nkf_char c, FILE *f)
+static nkf_char
+url_ungetc(nkf_char c, FILE *f)
 {
     return (*i_uungetc)(c, f);
 }
 #endif
 
 #ifdef NUMCHAR_OPTION
-nkf_char numchar_getc(FILE *f)
+static nkf_char
+numchar_getc(FILE *f)
 {
     nkf_char (*g)(FILE *) = i_ngetc;
     nkf_char (*u)(nkf_char c ,FILE *f) = i_nungetc;
@@ -3955,50 +4103,51 @@
 
     buf[i] = (*g)(f);
     if (buf[i] == '&'){
-        buf[++i] = (*g)(f);
-        if (buf[i] == '#'){
-            c = 0;
-            buf[++i] = (*g)(f);
-            if (buf[i] == 'x' || buf[i] == 'X'){
-                for (j = 0; j < 7; j++){
-                    buf[++i] = (*g)(f);
-                    if (!nkf_isxdigit(buf[i])){
-                        if (buf[i] != ';'){
-                            c = -1;
-                        }
-                        break;
-                    }
-                    c <<= 4;
-                    c |= hex2bin(buf[i]);
-                }
-            }else{
-                for (j = 0; j < 8; j++){
-                    if (j){
-                        buf[++i] = (*g)(f);
-                    }
-                    if (!nkf_isdigit(buf[i])){
-                        if (buf[i] != ';'){
-                            c = -1;
-                        }
-                        break;
-                    }
-                    c *= 10;
-                    c += hex2bin(buf[i]);
-                }
-            }
-        }
+	buf[++i] = (*g)(f);
+	if (buf[i] == '#'){
+	    c = 0;
+	    buf[++i] = (*g)(f);
+	    if (buf[i] == 'x' || buf[i] == 'X'){
+		for (j = 0; j < 7; j++){
+		    buf[++i] = (*g)(f);
+		    if (!nkf_isxdigit(buf[i])){
+			if (buf[i] != ';'){
+			    c = -1;
+			}
+			break;
+		    }
+		    c <<= 4;
+		    c |= hex2bin(buf[i]);
+		}
+	    }else{
+		for (j = 0; j < 8; j++){
+		    if (j){
+			buf[++i] = (*g)(f);
+		    }
+		    if (!nkf_isdigit(buf[i])){
+			if (buf[i] != ';'){
+			    c = -1;
+			}
+			break;
+		    }
+		    c *= 10;
+		    c += hex2bin(buf[i]);
+		}
+	    }
+	}
     }
     if (c != -1){
-        return CLASS_UNICODE | c;
+	return nkf_char_unicode_new(c);
     }
     while (i > 0){
-        (*u)(buf[i], f);
-        --i;
+	(*u)(buf[i], f);
+	--i;
     }
     return buf[0];
 }
 
-nkf_char numchar_ungetc(nkf_char c, FILE *f)
+static nkf_char
+numchar_ungetc(nkf_char c, FILE *f)
 {
     return (*i_nungetc)(c, f);
 }
@@ -4007,7 +4156,8 @@
 #ifdef UNICODE_NORMALIZATION
 
 /* Normalization Form C */
-nkf_char nfc_getc(FILE *f)
+static nkf_char
+nfc_getc(FILE *f)
 {
     nkf_char (*g)(FILE *f) = i_nfc_getc;
     nkf_char (*u)(nkf_char c ,FILE *f) = i_nfc_ungetc;
@@ -4043,35 +4193,37 @@
     return buf[0];
 }
 
-nkf_char nfc_ungetc(nkf_char c, FILE *f)
+static nkf_char
+nfc_ungetc(nkf_char c, FILE *f)
 {
     return (*i_nfc_ungetc)(c, f);
 }
 #endif /* UNICODE_NORMALIZATION */
 
 
-static nkf_char base64decode(nkf_char c)
+static nkf_char
+base64decode(nkf_char c)
 {
     int             i;
     if (c > '@') {
-        if (c < '[') {
-            i = c - 'A';                        /* A..Z 0-25 */
+	if (c < '[') {
+	    i = c - 'A';                        /* A..Z 0-25 */
 	} else if (c == '_') {
 	    i = '?'         /* 63 */ ;          /* _  63 */
-        } else {
-            i = c - 'G'     /* - 'a' + 26 */ ;  /* a..z 26-51 */
+	} else {
+	    i = c - 'G'     /* - 'a' + 26 */ ;  /* a..z 26-51 */
 	}
     } else if (c > '/') {
-        i = c - '0' + '4'   /* - '0' + 52 */ ;  /* 0..9 52-61 */
+	i = c - '0' + '4'   /* - '0' + 52 */ ;  /* 0..9 52-61 */
     } else if (c == '+' || c == '-') {
-        i = '>'             /* 62 */ ;          /* + and -  62 */
+	i = '>'             /* 62 */ ;          /* + and -  62 */
     } else {
-        i = '?'             /* 63 */ ;          /* / 63 */
+	i = '?'             /* 63 */ ;          /* / 63 */
     }
     return (i);
 }
 
-nkf_char
+static nkf_char
 mime_getc(FILE *f)
 {
     nkf_char c1, c2, c3, c4, cc;
@@ -4082,7 +4234,7 @@
     nkf_char lwsp_size = 128;
 
     if (mime_input_state.top != mime_input_state.last) {  /* Something is in FIFO */
-        return  mime_input_buf(mime_input_state.top++);
+	return  mime_input_buf(mime_input_state.top++);
     }
     if (mime_decode_mode==1 ||mime_decode_mode==FALSE) {
 	mime_decode_mode=FALSE;
@@ -4091,26 +4243,26 @@
     }
 
     if (mimebuf_f == FIXED_MIME)
-        exit_mode = mime_decode_mode;
+	exit_mode = mime_decode_mode;
     else
-        exit_mode = FALSE;
+	exit_mode = FALSE;
     if (mime_decode_mode == 'Q') {
-        if ((c1 = (*i_mgetc)(f)) == EOF) return (EOF);
-restart_mime_q:
-        if (c1=='_' && mimebuf_f != FIXED_MIME) return SP;
+	if ((c1 = (*i_mgetc)(f)) == EOF) return (EOF);
+      restart_mime_q:
+	if (c1=='_' && mimebuf_f != FIXED_MIME) return SP;
 	if (c1<=SP || DEL<=c1) {
 	    mime_decode_mode = exit_mode; /* prepare for quit */
 	    return c1;
 	}
-        if (c1!='=' && (c1!='?' || mimebuf_f == FIXED_MIME)) {
+	if (c1!='=' && (c1!='?' || mimebuf_f == FIXED_MIME)) {
 	    return c1;
 	}
 
-        mime_decode_mode = exit_mode; /* prepare for quit */
-        if ((c2 = (*i_mgetc)(f)) == EOF) return (EOF);
-        if (c1=='?'&&c2=='=' && mimebuf_f != FIXED_MIME) {
-            /* end Q encoding */
-            input_mode = exit_mode;
+	mime_decode_mode = exit_mode; /* prepare for quit */
+	if ((c2 = (*i_mgetc)(f)) == EOF) return (EOF);
+	if (c1=='?'&&c2=='=' && mimebuf_f != FIXED_MIME) {
+	    /* end Q encoding */
+	    input_mode = exit_mode;
 	    lwsp_count = 0;
 	    lwsp_buf = malloc((lwsp_size+5)*sizeof(char));
 	    if (lwsp_buf==NULL) {
@@ -4168,57 +4320,57 @@
 		c1 = lwsp_buf[0];
 	    }
 	    free(lwsp_buf);
-            return c1;
-        }
-        if (c1=='='&&c2<SP) { /* this is soft wrap */
-            while((c1 =  (*i_mgetc)(f)) <=SP) {
+	    return c1;
+	}
+	if (c1=='='&&c2<SP) { /* this is soft wrap */
+	    while((c1 =  (*i_mgetc)(f)) <=SP) {
 		if ((c1 = (*i_mgetc)(f)) == EOF) return (EOF);
 	    }
-            mime_decode_mode = 'Q'; /* still in MIME */
+	    mime_decode_mode = 'Q'; /* still in MIME */
 	    goto restart_mime_q;
 	}
-        if (c1=='?') {
-            mime_decode_mode = 'Q'; /* still in MIME */
-            (*i_mungetc)(c2,f);
-            return c1;
-        }
-        if ((c3 = (*i_mgetc)(f)) == EOF) return (EOF);
-        if (c2<=SP) return c2;
-        mime_decode_mode = 'Q'; /* still in MIME */
-        return ((hex2bin(c2)<<4) + hex2bin(c3));
+	if (c1=='?') {
+	    mime_decode_mode = 'Q'; /* still in MIME */
+	    (*i_mungetc)(c2,f);
+	    return c1;
+	}
+	if ((c3 = (*i_mgetc)(f)) == EOF) return (EOF);
+	if (c2<=SP) return c2;
+	mime_decode_mode = 'Q'; /* still in MIME */
+	return ((hex2bin(c2)<<4) + hex2bin(c3));
     }
 
     if (mime_decode_mode != 'B') {
-        mime_decode_mode = FALSE;
-        return (*i_mgetc)(f);
+	mime_decode_mode = FALSE;
+	return (*i_mgetc)(f);
     }
 
 
     /* Base64 encoding */
     /*
-        MIME allows line break in the middle of
-        Base64, but we are very pessimistic in decoding
-        in unbuf mode because MIME encoded code may broken by
-        less or editor's control sequence (such as ESC-[-K in unbuffered
-        mode. ignore incomplete MIME.
-    */
+       MIME allows line break in the middle of
+       Base64, but we are very pessimistic in decoding
+       in unbuf mode because MIME encoded code may broken by
+       less or editor's control sequence (such as ESC-[-K in unbuffered
+       mode. ignore incomplete MIME.
+     */
     mode = mime_decode_mode;
     mime_decode_mode = exit_mode;  /* prepare for quit */
 
     while ((c1 = (*i_mgetc)(f))<=SP) {
-        if (c1==EOF)
-            return (EOF);
+	if (c1==EOF)
+	    return (EOF);
     }
-mime_c2_retry:
+  mime_c2_retry:
     if ((c2 = (*i_mgetc)(f))<=SP) {
-        if (c2==EOF)
-            return (EOF);
+	if (c2==EOF)
+	    return (EOF);
 	if (mime_f != STRICT_MIME) goto mime_c2_retry;
-        if (mimebuf_f!=FIXED_MIME) input_mode = ASCII;
-        return c2;
+	if (mimebuf_f!=FIXED_MIME) input_mode = ASCII;
+	return c2;
     }
     if ((c1 == '?') && (c2 == '=')) {
-        input_mode = ASCII;
+	input_mode = ASCII;
 	lwsp_count = 0;
 	lwsp_buf = malloc((lwsp_size+5)*sizeof(char));
 	if (lwsp_buf==NULL) {
@@ -4279,23 +4431,23 @@
 	    c1 = lwsp_buf[0];
 	}
 	free(lwsp_buf);
-        return c1;
+	return c1;
     }
-mime_c3_retry:
+  mime_c3_retry:
     if ((c3 = (*i_mgetc)(f))<=SP) {
-        if (c3==EOF)
-            return (EOF);
+	if (c3==EOF)
+	    return (EOF);
 	if (mime_f != STRICT_MIME) goto mime_c3_retry;
-        if (mimebuf_f!=FIXED_MIME) input_mode = ASCII;
-        return c3;
+	if (mimebuf_f!=FIXED_MIME) input_mode = ASCII;
+	return c3;
     }
-mime_c4_retry:
+  mime_c4_retry:
     if ((c4 = (*i_mgetc)(f))<=SP) {
-        if (c4==EOF)
-            return (EOF);
+	if (c4==EOF)
+	    return (EOF);
 	if (mime_f != STRICT_MIME) goto mime_c4_retry;
-        if (mimebuf_f!=FIXED_MIME) input_mode = ASCII;
-        return c4;
+	if (mimebuf_f!=FIXED_MIME) input_mode = ASCII;
+	return c4;
     }
 
     mime_decode_mode = mode; /* still in MIME sigh... */
@@ -4308,22 +4460,22 @@
     t4 = 0x3f & base64decode(c4);
     cc = ((t1 << 2) & 0x0fc) | ((t2 >> 4) & 0x03);
     if (c2 != '=') {
-        mime_input_buf(mime_input_state.last++) = (unsigned char)cc;
-        cc = ((t2 << 4) & 0x0f0) | ((t3 >> 2) & 0x0f);
-        if (c3 != '=') {
-            mime_input_buf(mime_input_state.last++) = (unsigned char)cc;
-            cc = ((t3 << 6) & 0x0c0) | (t4 & 0x3f);
-            if (c4 != '=')
-                mime_input_buf(mime_input_state.last++) = (unsigned char)cc;
-        }
+	mime_input_buf(mime_input_state.last++) = (unsigned char)cc;
+	cc = ((t2 << 4) & 0x0f0) | ((t3 >> 2) & 0x0f);
+	if (c3 != '=') {
+	    mime_input_buf(mime_input_state.last++) = (unsigned char)cc;
+	    cc = ((t3 << 6) & 0x0c0) | (t4 & 0x3f);
+	    if (c4 != '=')
+		mime_input_buf(mime_input_state.last++) = (unsigned char)cc;
+	}
     } else {
-        return c1;
+	return c1;
     }
     return  mime_input_buf(mime_input_state.top++);
 }
 
 static const char basis_64[] =
-   "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
 
 #define MIMEOUT_BUF_LENGTH (60)
 static struct {
@@ -4334,7 +4486,8 @@
 
 /*nkf_char mime_lastchar2, mime_lastchar1;*/
 
-static void open_mime(nkf_char mode)
+static void
+open_mime(nkf_char mode)
 {
     const unsigned char *p;
     int i;
@@ -4350,7 +4503,7 @@
     i = 0;
     if (base64_count>45) {
 	if (mimeout_state.count>0 && nkf_isblank(mimeout_state.buf[i])){
-            (*o_mputc)(mimeout_state.buf[i]);
+	    (*o_mputc)(mimeout_state.buf[i]);
 	    i++;
 	}
 	PUT_NEWLINE((*o_mputc));
@@ -4358,7 +4511,7 @@
 	base64_count = 1;
 	if (mimeout_state.count>0
 	    && (mimeout_state.buf[i]==SP || mimeout_state.buf[i]==TAB
-	    	|| mimeout_state.buf[i]==CR || mimeout_state.buf[i]==LF)) {
+		|| mimeout_state.buf[i]==CR || mimeout_state.buf[i]==LF)) {
 	    i++;
 	}
     }
@@ -4372,8 +4525,8 @@
 	}
     }
     while(*p) {
-        (*o_mputc)(*p++);
-        base64_count ++;
+	(*o_mputc)(*p++);
+	base64_count ++;
     }
     j = mimeout_state.count;
     mimeout_state.count = 0;
@@ -4382,25 +4535,26 @@
     }
 }
 
-static void mime_prechar(nkf_char c2, nkf_char c1)
+static void
+mime_prechar(nkf_char c2, nkf_char c1)
 {
     if (mimeout_mode > 0){
-        if (c2 == EOF){
-            if (base64_count + mimeout_state.count/3*4> 73){
-                (*o_base64conv)(EOF,0);
-                OCONV_NEWLINE((*o_base64conv));
-                (*o_base64conv)(0,SP);
-                base64_count = 1;
-            }
-        } else {
-            if (base64_count + mimeout_state.count/3*4> 66) {
-                (*o_base64conv)(EOF,0);
-                OCONV_NEWLINE((*o_base64conv));
-                (*o_base64conv)(0,SP);
-                base64_count = 1;
-                mimeout_mode = -1;
-            }
-        }
+	if (c2 == EOF){
+	    if (base64_count + mimeout_state.count/3*4> 73){
+		(*o_base64conv)(EOF,0);
+		OCONV_NEWLINE((*o_base64conv));
+		(*o_base64conv)(0,SP);
+		base64_count = 1;
+	    }
+	} else {
+	    if (base64_count + mimeout_state.count/3*4> 66) {
+		(*o_base64conv)(EOF,0);
+		OCONV_NEWLINE((*o_base64conv));
+		(*o_base64conv)(0,SP);
+		base64_count = 1;
+		mimeout_mode = -1;
+	    }
+	}
     } else if (c2) {
 	if (c2 != EOF && base64_count + mimeout_state.count/3*4> 60) {
 	    mimeout_mode =  (output_mode==ASCII ||output_mode == ISO_8859_1) ? 'Q' : 'B';
@@ -4414,7 +4568,8 @@
     }
 }
 
-static void close_mime(void)
+static void
+close_mime(void)
 {
     (*o_mputc)('?');
     (*o_mputc)('=');
@@ -4422,7 +4577,8 @@
     mimeout_mode = 0;
 }
 
-static void eof_mime(void)
+static void
+eof_mime(void)
 {
     switch(mimeout_mode) {
     case 'Q':
@@ -4448,7 +4604,8 @@
     }
 }
 
-static void mimeout_addchar(nkf_char c)
+static void
+mimeout_addchar(nkf_char c)
 {
     switch(mimeout_mode) {
     case 'Q':
@@ -4464,60 +4621,61 @@
 	    (*o_mputc)(c);
 	    base64_count++;
 	}
-        break;
+	break;
     case 'B':
-        mimeout_state.state=c;
-        (*o_mputc)(basis_64[c>>2]);
-        mimeout_mode=2;
-        base64_count ++;
-        break;
+	mimeout_state.state=c;
+	(*o_mputc)(basis_64[c>>2]);
+	mimeout_mode=2;
+	base64_count ++;
+	break;
     case 2:
-        (*o_mputc)(basis_64[((mimeout_state.state & 0x3)<< 4) | ((c & 0xF0) >> 4)]);
-        mimeout_state.state=c;
-        mimeout_mode=1;
-        base64_count ++;
-        break;
+	(*o_mputc)(basis_64[((mimeout_state.state & 0x3)<< 4) | ((c & 0xF0) >> 4)]);
+	mimeout_state.state=c;
+	mimeout_mode=1;
+	base64_count ++;
+	break;
     case 1:
-        (*o_mputc)(basis_64[((mimeout_state.state & 0xF) << 2) | ((c & 0xC0) >>6)]);
-        (*o_mputc)(basis_64[c & 0x3F]);
-        mimeout_mode='B';
-        base64_count += 2;
-        break;
+	(*o_mputc)(basis_64[((mimeout_state.state & 0xF) << 2) | ((c & 0xC0) >>6)]);
+	(*o_mputc)(basis_64[c & 0x3F]);
+	mimeout_mode='B';
+	base64_count += 2;
+	break;
     default:
 	(*o_mputc)(c);
 	base64_count++;
-        break;
+	break;
     }
 }
 
-static void mime_putc(nkf_char c)
+static void
+mime_putc(nkf_char c)
 {
     int i, j;
     nkf_char lastchar;
 
     if (mimeout_f == FIXED_MIME){
-        if (mimeout_mode == 'Q'){
-            if (base64_count > 71){
-                if (c!=CR && c!=LF) {
-                    (*o_mputc)('=');
-                    PUT_NEWLINE((*o_mputc));
-                }
-                base64_count = 0;
-            }
-        }else{
-            if (base64_count > 71){
-                eof_mime();
-                PUT_NEWLINE((*o_mputc));
-                base64_count = 0;
-            }
-            if (c == EOF) { /* c==EOF */
-                eof_mime();
-            }
-        }
-        if (c != EOF) { /* c==EOF */
-            mimeout_addchar(c);
-        }
-        return;
+	if (mimeout_mode == 'Q'){
+	    if (base64_count > 71){
+		if (c!=CR && c!=LF) {
+		    (*o_mputc)('=');
+		    PUT_NEWLINE((*o_mputc));
+		}
+		base64_count = 0;
+	    }
+	}else{
+	    if (base64_count > 71){
+		eof_mime();
+		PUT_NEWLINE((*o_mputc));
+		base64_count = 0;
+	    }
+	    if (c == EOF) { /* c==EOF */
+		eof_mime();
+	    }
+	}
+	if (c != EOF) { /* c==EOF */
+	    mimeout_addchar(c);
+	}
+	return;
     }
 
     /* mimeout_f != FIXED_MIME */
@@ -4550,24 +4708,24 @@
 		mimeout_addchar(mimeout_state.buf[i]);
 	    }
 	}
-        return;
+	return;
     }
 
     if (mimeout_state.count > 0){
-        lastchar = mimeout_state.buf[mimeout_state.count - 1];
+	lastchar = mimeout_state.buf[mimeout_state.count - 1];
     }else{
-        lastchar = -1;
+	lastchar = -1;
     }
 
     if (mimeout_mode=='Q') {
-        if (c <= DEL && (output_mode==ASCII ||output_mode == ISO_8859_1)) {
+	if (c <= DEL && (output_mode==ASCII ||output_mode == ISO_8859_1)) {
 	    if (c == CR || c == LF) {
 		close_mime();
 		(*o_mputc)(c);
 		base64_count = 0;
 		return;
-            } else if (c <= SP) {
-                close_mime();
+	    } else if (c <= SP) {
+		close_mime();
 		if (base64_count > 70) {
 		    PUT_NEWLINE((*o_mputc));
 		    base64_count = 0;
@@ -4576,7 +4734,7 @@
 		    (*o_mputc)(SP);
 		    base64_count++;
 		}
-            } else {
+	    } else {
 		if (base64_count > 70) {
 		    close_mime();
 		    PUT_NEWLINE((*o_mputc));
@@ -4591,129 +4749,129 @@
 	    }
 	    (*o_mputc)(c);
 	    base64_count++;
-        }
-        return;
+	}
+	return;
     }
 
     if (mimeout_mode <= 0) {
-        if (c <= DEL && (output_mode==ASCII ||output_mode == ISO_8859_1)) {
-            if (nkf_isspace(c)) {
+	if (c <= DEL && (output_mode==ASCII ||output_mode == ISO_8859_1)) {
+	    if (nkf_isspace(c)) {
 		int flag = 0;
 		if (mimeout_mode == -1) {
 		    flag = 1;
 		}
-                if (c==CR || c==LF) {
+		if (c==CR || c==LF) {
 		    if (flag) {
 			open_mime(output_mode);
 			output_mode = 0;
 		    } else {
 			base64_count = 0;
 		    }
-                }
-                for (i=0;i<mimeout_state.count;i++) {
-                    (*o_mputc)(mimeout_state.buf[i]);
-                    if (mimeout_state.buf[i] == CR || mimeout_state.buf[i] == LF){
-                        base64_count = 0;
-                    }else{
-                        base64_count++;
-                    }
-                }
+		}
+		for (i=0;i<mimeout_state.count;i++) {
+		    (*o_mputc)(mimeout_state.buf[i]);
+		    if (mimeout_state.buf[i] == CR || mimeout_state.buf[i] == LF){
+			base64_count = 0;
+		    }else{
+			base64_count++;
+		    }
+		}
 		if (flag) {
 		    eof_mime();
 		    base64_count = 0;
 		    mimeout_mode = 0;
-                }
+		}
 		mimeout_state.buf[0] = (char)c;
 		mimeout_state.count = 1;
-            }else{
-                if (base64_count > 1
-                    && base64_count + mimeout_state.count > 76
+	    }else{
+		if (base64_count > 1
+		    && base64_count + mimeout_state.count > 76
 		    && mimeout_state.buf[0] != CR && mimeout_state.buf[0] != LF){
-                    PUT_NEWLINE((*o_mputc));
-                    base64_count = 0;
-                    if (!nkf_isspace(mimeout_state.buf[0])){
-                        (*o_mputc)(SP);
-                        base64_count++;
-                    }
-                }
-                mimeout_state.buf[mimeout_state.count++] = (char)c;
-                if (mimeout_state.count>MIMEOUT_BUF_LENGTH) {
-                    open_mime(output_mode);
-                }
-            }
-            return;
-        }else{
-            if (lastchar==CR || lastchar == LF){
-                for (i=0;i<mimeout_state.count;i++) {
-                    (*o_mputc)(mimeout_state.buf[i]);
-                }
-                base64_count = 0;
-                mimeout_state.count = 0;
-            }
-            if (lastchar==SP) {
-                for (i=0;i<mimeout_state.count-1;i++) {
-                    (*o_mputc)(mimeout_state.buf[i]);
-                    base64_count++;
-                }
-                mimeout_state.buf[0] = SP;
-                mimeout_state.count = 1;
-            }
-            open_mime(output_mode);
-        }
+		    PUT_NEWLINE((*o_mputc));
+		    base64_count = 0;
+		    if (!nkf_isspace(mimeout_state.buf[0])){
+			(*o_mputc)(SP);
+			base64_count++;
+		    }
+		}
+		mimeout_state.buf[mimeout_state.count++] = (char)c;
+		if (mimeout_state.count>MIMEOUT_BUF_LENGTH) {
+		    open_mime(output_mode);
+		}
+	    }
+	    return;
+	}else{
+	    if (lastchar==CR || lastchar == LF){
+		for (i=0;i<mimeout_state.count;i++) {
+		    (*o_mputc)(mimeout_state.buf[i]);
+		}
+		base64_count = 0;
+		mimeout_state.count = 0;
+	    }
+	    if (lastchar==SP) {
+		for (i=0;i<mimeout_state.count-1;i++) {
+		    (*o_mputc)(mimeout_state.buf[i]);
+		    base64_count++;
+		}
+		mimeout_state.buf[0] = SP;
+		mimeout_state.count = 1;
+	    }
+	    open_mime(output_mode);
+	}
     }else{
-        /* mimeout_mode == 'B', 1, 2 */
-        if ( c<=DEL && (output_mode==ASCII ||output_mode == ISO_8859_1)) {
-            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) {
-                    eof_mime();
-                    for (i=0;i<mimeout_state.count;i++) {
-                        (*o_mputc)(mimeout_state.buf[i]);
-                    }
-                    base64_count = 0;
-                    mimeout_state.count = 0;
-                }
-                mimeout_state.buf[mimeout_state.count++] = (char)c;
+	/* mimeout_mode == 'B', 1, 2 */
+	if ( c<=DEL && (output_mode==ASCII ||output_mode == ISO_8859_1)) {
+	    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) {
+		    eof_mime();
+		    for (i=0;i<mimeout_state.count;i++) {
+			(*o_mputc)(mimeout_state.buf[i]);
+		    }
+		    base64_count = 0;
+		    mimeout_state.count = 0;
+		}
+		mimeout_state.buf[mimeout_state.count++] = (char)c;
 		return;
-            }
-            if (c==SP || c==TAB || c==CR || c==LF) {
-                for (i=0;i<mimeout_state.count;i++) {
-                    if (SP<mimeout_state.buf[i] && mimeout_state.buf[i]<DEL) {
-                        eof_mime();
-                        for (i=0;i<mimeout_state.count;i++) {
-                            (*o_mputc)(mimeout_state.buf[i]);
-                            base64_count++;
-                        }
-                        mimeout_state.count = 0;
-                    }
-                }
-                mimeout_state.buf[mimeout_state.count++] = (char)c;
-                if (mimeout_state.count>MIMEOUT_BUF_LENGTH) {
-                    eof_mime();
-                    for (i=0;i<mimeout_state.count;i++) {
-                        (*o_mputc)(mimeout_state.buf[i]);
-                        base64_count++;
-                    }
-                    mimeout_state.count = 0;
-                }
-                return;
 	    }
-            if (mimeout_state.count>0 && SP<c && c!='=') {
-                mimeout_state.buf[mimeout_state.count++] = (char)c;
-                if (mimeout_state.count>MIMEOUT_BUF_LENGTH) {
-                    j = mimeout_state.count;
-                    mimeout_state.count = 0;
-                    for (i=0;i<j;i++) {
-                        mimeout_addchar(mimeout_state.buf[i]);
-                    }
-                }
-                return;
-            }
-        }
+	    if (c==SP || c==TAB || c==CR || c==LF) {
+		for (i=0;i<mimeout_state.count;i++) {
+		    if (SP<mimeout_state.buf[i] && mimeout_state.buf[i]<DEL) {
+			eof_mime();
+			for (i=0;i<mimeout_state.count;i++) {
+			    (*o_mputc)(mimeout_state.buf[i]);
+			    base64_count++;
+			}
+			mimeout_state.count = 0;
+		    }
+		}
+		mimeout_state.buf[mimeout_state.count++] = (char)c;
+		if (mimeout_state.count>MIMEOUT_BUF_LENGTH) {
+		    eof_mime();
+		    for (i=0;i<mimeout_state.count;i++) {
+			(*o_mputc)(mimeout_state.buf[i]);
+			base64_count++;
+		    }
+		    mimeout_state.count = 0;
+		}
+		return;
+	    }
+	    if (mimeout_state.count>0 && SP<c && c!='=') {
+		mimeout_state.buf[mimeout_state.count++] = (char)c;
+		if (mimeout_state.count>MIMEOUT_BUF_LENGTH) {
+		    j = mimeout_state.count;
+		    mimeout_state.count = 0;
+		    for (i=0;i<j;i++) {
+			mimeout_addchar(mimeout_state.buf[i]);
+		    }
+		}
+		return;
+	    }
+	}
     }
     if (mimeout_state.count>0) {
 	j = mimeout_state.count;
@@ -4735,7 +4893,8 @@
     mimeout_addchar(c);
 }
 
-void base64_conv(nkf_char c2, nkf_char c1)
+static void
+base64_conv(nkf_char c2, nkf_char c1)
 {
     mime_prechar(c2, c1);
     (*o_base64conv)(c2,c1);
@@ -4750,34 +4909,36 @@
     size_t output_buffer_size;
 }
 
-nkf_iconv_t nkf_iconv_new(char *tocode, char *fromcode)
+static nkf_iconv_t
+nkf_iconv_new(char *tocode, char *fromcode)
 {
     nkf_iconv_t converter;
 
     converter->input_buffer_size = IOBUF_SIZE;
     converter->input_buffer = malloc(converter->input_buffer_size);
     if (converter->input_buffer == NULL)
-        perror("can't malloc");
+	perror("can't malloc");
 
     converter->output_buffer_size = IOBUF_SIZE * 2;
     converter->output_buffer = malloc(converter->output_buffer_size);
     if (converter->output_buffer == NULL)
-        perror("can't malloc");
+	perror("can't malloc");
 
     converter->cd = iconv_open(tocode, fromcode);
     if (converter->cd == (iconv_t)-1)
     {
-        switch (errno) {
-        case EINVAL:
-            perror(fprintf("iconv doesn't support %s to %s conversion.", fromcode, tocode));
-            return -1;
-        default:
-            perror("can't iconv_open");
-        }
+	switch (errno) {
+	case EINVAL:
+	    perror(fprintf("iconv doesn't support %s to %s conversion.", fromcode, tocode));
+	    return -1;
+	default:
+	    perror("can't iconv_open");
+	}
     }
 }
 
-size_t nkf_iconv_convert(nkf_iconv_t *converter, FILE *input)
+static size_t
+nkf_iconv_convert(nkf_iconv_t *converter, FILE *input)
 {
     size_t invalid = (size_t)0;
     char *input_buffer = converter->input_buffer;
@@ -4787,61 +4948,63 @@
     int c;
 
     do {
-        if (c != EOF) {
-            while ((c = (*i_getc)(f)) != EOF) {
-                input_buffer[input_length++] = c;
-                if (input_length < converter->input_buffer_size) break;
-            }
-        }
+	if (c != EOF) {
+	    while ((c = (*i_getc)(f)) != EOF) {
+		input_buffer[input_length++] = c;
+		if (input_length < converter->input_buffer_size) break;
+	    }
+	}
 
-        size_t ret = iconv(converter->cd, &input_buffer, &input_length, &output_buffer, &output_length);
-        while (output_length-- > 0) {
-            (*o_putc)(output_buffer[converter->output_buffer_size-output_length]);
-        }
-        if (ret == (size_t) - 1) {
-            switch (errno) {
-            case EINVAL:
-                if (input_buffer != converter->input_buffer)
-                    memmove(converter->input_buffer, input_buffer, input_length);
-                break;
-            case E2BIG:
-                converter->output_buffer_size *= 2;
-                output_buffer = realloc(converter->outbuf, converter->output_buffer_size);
-                if (output_buffer == NULL) {
-                    perror("can't realloc");
-                    return -1;
-                }
-                converter->output_buffer = output_buffer;
-                break;
-            default:
-                perror("can't iconv");
-                return -1;
-            }
-        } else {
-            invalid += ret;
-        }
+	size_t ret = iconv(converter->cd, &input_buffer, &input_length, &output_buffer, &output_length);
+	while (output_length-- > 0) {
+	    (*o_putc)(output_buffer[converter->output_buffer_size-output_length]);
+	}
+	if (ret == (size_t) - 1) {
+	    switch (errno) {
+	    case EINVAL:
+		if (input_buffer != converter->input_buffer)
+		    memmove(converter->input_buffer, input_buffer, input_length);
+		break;
+	    case E2BIG:
+		converter->output_buffer_size *= 2;
+		output_buffer = realloc(converter->outbuf, converter->output_buffer_size);
+		if (output_buffer == NULL) {
+		    perror("can't realloc");
+		    return -1;
+		}
+		converter->output_buffer = output_buffer;
+		break;
+	    default:
+		perror("can't iconv");
+		return -1;
+	    }
+	} else {
+	    invalid += ret;
+	}
     } while (1);
 
     return invalid;
 }
 
 
-void nkf_iconv_close(nkf_iconv_t *convert)
+static void
+nkf_iconv_close(nkf_iconv_t *convert)
 {
-        free(converter->inbuf);
-        free(converter->outbuf);
-        iconv_close(converter->cd);
+    free(converter->inbuf);
+    free(converter->outbuf);
+    iconv_close(converter->cd);
 }
 #endif
 
 
-void reinit(void)
+static void
+reinit(void)
 {
     {
-        struct input_code *p = input_code_list;
-        while (p->name){
-            status_reinit(p++);
-        }
+	struct input_code *p = input_code_list;
+	while (p->name){
+	    status_reinit(p++);
+	}
     }
     unbuf_f = FALSE;
     estab_f = FALSE;
@@ -4897,10 +5060,10 @@
     x0213_f = FALSE;
 #endif
     {
-        int i;
-        for (i = 0; i < 256; i++){
-            prefix_table[i] = 0;
-        }
+	int i;
+	for (i = 0; i < 256; i++){
+	    prefix_table[i] = 0;
+	}
     }
     hold_count = 0;
     mimeout_state.count = 0;
@@ -4933,7 +5096,6 @@
     i_mungetc_buf = std_ungetc;
     output_mode = ASCII;
     input_mode =  ASCII;
-    shift_mode =  FALSE;
     mime_decode_mode = FALSE;
     file_out_f = FALSE;
     eolmode_f = 0;
@@ -4953,12 +5115,17 @@
 #endif /*WIN32DLL*/
 }
 
-void module_connection(void)
+static int
+module_connection(void)
 {
     if (input_encoding) set_input_encoding(input_encoding);
     if (!output_encoding) {
 	output_encoding = nkf_default_encoding();
     }
+    if (!output_encoding) {
+	if (noout_f || guess_f) output_encoding = nkf_enc_from_index(ISO_2022_JP);
+	else return -1;
+    }
     set_output_encoding(output_encoding);
     oconv = nkf_enc_to_oconv(output_encoding);
     o_putc = std_putc;
@@ -4968,7 +5135,7 @@
     /* output redicrection */
 #ifdef CHECK_OPTION
     if (noout_f || guess_f){
-        o_putc = no_putc;
+	o_putc = no_putc;
     }
 #endif
     if (mimeout_f) {
@@ -5005,24 +5172,24 @@
     /* input redicrection */
 #ifdef INPUT_OPTION
     if (cap_f){
-        i_cgetc = i_getc; i_getc = cap_getc;
-        i_cungetc = i_ungetc; i_ungetc= cap_ungetc;
+	i_cgetc = i_getc; i_getc = cap_getc;
+	i_cungetc = i_ungetc; i_ungetc= cap_ungetc;
     }
     if (url_f){
-        i_ugetc = i_getc; i_getc = url_getc;
-        i_uungetc = i_ungetc; i_ungetc= url_ungetc;
+	i_ugetc = i_getc; i_getc = url_getc;
+	i_uungetc = i_ungetc; i_ungetc= url_ungetc;
     }
 #endif
 #ifdef NUMCHAR_OPTION
     if (numchar_f){
-        i_ngetc = i_getc; i_getc = numchar_getc;
-        i_nungetc = i_ungetc; i_ungetc= numchar_ungetc;
+	i_ngetc = i_getc; i_getc = numchar_getc;
+	i_nungetc = i_ungetc; i_ungetc= numchar_ungetc;
     }
 #endif
 #ifdef UNICODE_NORMALIZATION
     if (nfc_f){
-        i_nfc_getc = i_getc; i_getc = nfc_getc;
-        i_nfc_ungetc = i_ungetc; i_ungetc= nfc_ungetc;
+	i_nfc_getc = i_getc; i_getc = nfc_getc;
+	i_nfc_ungetc = i_ungetc; i_ungetc= nfc_ungetc;
     }
 #endif
     if (mime_f && mimebuf_f==FIXED_MIME) {
@@ -5034,17 +5201,18 @@
 	i_bungetc = i_ungetc; i_ungetc = broken_ungetc;
     }
     if (input_encoding) {
-        set_iconv(-TRUE, nkf_enc_to_iconv(input_encoding));
+	set_iconv(-TRUE, nkf_enc_to_iconv(input_encoding));
     } else {
-        set_iconv(FALSE, e_iconv);
+	set_iconv(FALSE, e_iconv);
     }
 
     {
-        struct input_code *p = input_code_list;
-        while (p->name){
-            status_reinit(p++);
-        }
+	struct input_code *p = input_code_list;
+	while (p->name){
+	    status_reinit(p++);
+	}
     }
+    return 0;
 }
 
 /*
@@ -5052,22 +5220,38 @@
  */
 
 #if !defined(PERL_XS) && !defined(WIN32DLL)
-nkf_char noconvert(FILE *f)
+static nkf_char
+noconvert(FILE *f)
 {
     nkf_char    c;
 
     if (nop_f == 2)
 	module_connection();
     while ((c = (*i_getc)(f)) != EOF)
-      (*o_putc)(c);
+	(*o_putc)(c);
     (*o_putc)(EOF);
     return 1;
 }
 #endif
 
-nkf_char kanji_convert(FILE *f)
+#define NEXT continue        /* no output, get next */
+#define SKIP c2=0;continue        /* no output, get next */
+#define MORE c2=c1;continue  /* need one more byte */
+#define SEND ;               /* output c1 and c2, get next */
+#define LAST break           /* end of loop, go closing  */
+#define set_input_mode(mode) do { \
+    input_mode = mode; \
+    shift_mode = 0; \
+    set_input_codename("ISO-2022-JP"); \
+    debug("ISO-2022-JP"); \
+} while (0)
+
+static int
+kanji_convert(FILE *f)
 {
-    nkf_char    c3, c2=0, c1, c0=0;
+    nkf_char c1=0, c2=0, c3=0, c4=0;
+    int shift_mode = 0; /* 0, 1, 2, 3 */
+    char g2 = 0;
     int is_8bit = FALSE;
 
     if (input_encoding && !nkf_enc_asciicompat(input_encoding)) {
@@ -5076,325 +5260,278 @@
 
     input_mode = ASCII;
     output_mode = ASCII;
-    shift_mode = FALSE;
 
-#define NEXT continue      /* no output, get next */
-#define SEND ;             /* output c1 and c2, get next */
-#define LAST break         /* end of loop, go closing  */
-
-    module_connection();
+    if (module_connection() < 0) {
+#if !defined(PERL_XS) && !defined(WIN32DLL)
+	fprintf(stderr, "no output encoding given\n");
+#endif
+	return -1;
+    }
     check_bom(f);
 
+#ifdef UTF8_INPUT_ENABLE
+    if(iconv == w_iconv32){
+	while ((c1 = (*i_getc)(f)) != EOF &&
+	       (c2 = (*i_getc)(f)) != EOF &&
+	       (c3 = (*i_getc)(f)) != EOF &&
+	       (c4 = (*i_getc)(f)) != EOF) {
+	    nkf_iconv_utf_32(c1, c2, c3, c4);
+	}
+	(*i_ungetc)(EOF, f);
+    }
+    else if (iconv == w_iconv16) {
+	while ((c1 = (*i_getc)(f)) != EOF &&
+	       (c2 = (*i_getc)(f)) != EOF) {
+	    if (nkf_iconv_utf_16(c1, c2, 0, 0) == -2 &&
+		(c3 = (*i_getc)(f)) != EOF &&
+		(c4 = (*i_getc)(f)) != EOF) {
+		nkf_iconv_utf_16(c1, c2, c3, c4);
+	    }
+	}
+	(*i_ungetc)(EOF, f);
+    }
+#endif
+
     while ((c1 = (*i_getc)(f)) != EOF) {
 #ifdef INPUT_CODE_FIX
 	if (!input_encoding)
 #endif
 	    code_status(c1);
-        if (c2) {
-            /* second byte */
-            if (c2 > ((input_encoding && nkf_enc_cp5022x_p(input_encoding)) ? 0x92 : DEL)) {
-                /* in case of 8th bit is on */
-                if (!estab_f&&!mime_decode_mode) {
-                    /* in case of not established yet */
-                    /* It is still ambiguious */
-                    if (h_conv(f, c2, c1)==EOF)
-                        LAST;
-                    else
-                        c2 = 0;
-                    NEXT;
-                } else {
+	if (c2) {
+	    /* second byte */
+	    if (c2 > DEL) {
+		/* in case of 8th bit is on */
+		if (!estab_f&&!mime_decode_mode) {
+		    /* in case of not established yet */
+		    /* It is still ambiguious */
+		    if (h_conv(f, c2, c1)==EOF) {
+			LAST;
+		    }
+		    else {
+			SKIP;
+		    }
+		}
+		else {
 		    /* in case of already established */
-		    if (c1 < AT) {
-			/* ignore bogus code and not CP5022x UCD */
-			c2 = 0;
-			NEXT;
+		    if (c1 < 0x40) {
+			/* ignore bogus code */
+			SKIP;
 		    } else {
 			SEND;
 		    }
 		}
-            } else
-                /* second byte, 7 bit code */
-                /* it might be kanji shitfted */
-                if ((c1 == DEL) || (c1 <= SP)) {
-                    /* ignore bogus first code */
-                    c2 = 0;
-                    NEXT;
-                } else
-                    SEND;
-        } else {
-            /* first byte */
-#ifdef UTF8_INPUT_ENABLE
-	    if (iconv == w_iconv16) {
-		if (input_endian == ENDIAN_BIG) {
-		    c2 = c1;
-		    if ((c1 = (*i_getc)(f)) != EOF) {
-			if (0xD8 <= c2 && c2 <= 0xDB) {
-			    if ((c0 = (*i_getc)(f)) != EOF) {
-				c0 <<= 8;
-				if ((c3 = (*i_getc)(f)) != EOF) {
-				    c0 |= c3;
-				} else c2 = EOF;
-			    } else c2 = EOF;
-			}
-		    } else c2 = EOF;
-		} else {
-		    if ((c2 = (*i_getc)(f)) != EOF) {
-			if (0xD8 <= c2 && c2 <= 0xDB) {
-			    if ((c3 = (*i_getc)(f)) != EOF) {
-				if ((c0 = (*i_getc)(f)) != EOF) {
-				    c0 <<= 8;
-				    c0 |= c3;
-				} else c2 = EOF;
-			    } else c2 = EOF;
-			}
-		    } else c2 = EOF;
-		}
+	    }
+	    else {
+		/* 2nd byte of 7 bit code or SJIS */
 		SEND;
-            } else if(iconv == w_iconv32){
-		int c3 = c1;
-		if((c2 = (*i_getc)(f)) != EOF &&
-		   (c1 = (*i_getc)(f)) != EOF &&
-		   (c0 = (*i_getc)(f)) != EOF){
-		    switch(input_endian){
-		    case ENDIAN_BIG:
-			c1 = (c2&0xFF)<<16 | (c1&0xFF)<<8 | (c0&0xFF);
-			break;
-		    case ENDIAN_LITTLE:
-			c1 = (c3&0xFF) | (c2&0xFF)<<8 | (c1&0xFF)<<16;
-			break;
-		    case ENDIAN_2143:
-			c1 = (c3&0xFF)<<16 | (c1&0xFF) | (c0&0xFF)<<8;
-			break;
-		    case ENDIAN_3412:
-			c1 = (c3&0xFF)<<8 | (c2&0xFF) | (c0&0xFF)<<16;
-			break;
+	    }
+	}
+	else {
+	    /* first byte */
+	    if (input_mode == JIS_X_0208 && DEL <= c1 && c1 < 0x92) {
+		/* CP5022x */
+		MORE;
+	    } else if (c1 > DEL) {
+		/* 8 bit code */
+		if (!estab_f && !iso8859_f) {
+		    /* not established yet */
+		    MORE;
+		} else { /* estab_f==TRUE */
+		    if (iso8859_f) {
+			c2 = ISO_8859_1;
+			c1 &= 0x7f;
+			SEND;
 		    }
-		    c2 = 0;
-		}else{
-		    c2 = EOF;
-		}
-		SEND;
-            } else
-#endif
-#ifdef NUMCHAR_OPTION
-            if (is_unicode_capsule(c1)){
-                SEND;
-	    } else
-#endif
-	    if (c1 > ((input_encoding && nkf_enc_cp5022x_p(input_encoding)) ? 0x92 : DEL)) {
-                /* 8 bit code */
-                if (!estab_f && !iso8859_f) {
-                    /* not established yet */
-                    c2 = c1;
-                    NEXT;
-                } else { /* estab_f==TRUE */
-                    if (iso8859_f) {
-                        c2 = ISO_8859_1;
-                        c1 &= 0x7f;
-                        SEND;
-                    } else if (SSP<=c1 && c1<0xe0 && iconv == s_iconv) {
-                        /* SJIS X0201 Case... */
-                        if (iso2022jp_f && !x0201_f) {
-                            (*oconv)(GETA1, GETA2);
-                            NEXT;
-                        } else {
-			    c2 = JIS_X_0201;
-			    c1 &= 0x7f;
-			    SEND;
-			}
-                    } else if (c1==SSO && iconv != s_iconv) {
-                        /* EUC X0201 Case */
-                        c1 = (*i_getc)(f);  /* skip SSO */
-                        code_status(c1);
-                        if (SSP<=c1 && c1<0xe0) {
-			    if (iso2022jp_f && !x0201_f) {
-				(*oconv)(GETA1, GETA2);
-				NEXT;
-			    } else {
-				c2 = JIS_X_0201;
-				c1 &= 0x7f;
-				SEND;
-			    }
-                        } else  { /* bogus code, skip SSO and one byte */
-                            NEXT;
-                        }
-		    } else if (ms_ucs_map_f == UCS_MAP_CP10001 &&
-			       (c1 == 0xFD || c1 == 0xFE)) {
-			/* CP10001 */
-			c2 = JIS_X_0201;
+		    else if ((iconv == s_iconv && 0xA0 <= c1 && c1 <= 0xDF) ||
+			     (ms_ucs_map_f == UCS_MAP_CP10001 && (c1 == 0xFD || c1 == 0xFE))) {
+			/* JIS X 0201 */
+			c2 = JIS_X_0201_1976_K;
 			c1 &= 0x7f;
 			SEND;
-                    } else {
-                       /* already established */
-                       c2 = c1;
-                       NEXT;
-                    }
-                }
-            } else if ((c1 > SP) && (c1 != DEL)) {
-                /* in case of Roman characters */
-                if (shift_mode) {
-                    /* output 1 shifted byte */
-                    if (iso8859_f) {
-                        c2 = ISO_8859_1;
-                        SEND;
-                    } else if (SP <= c1 && c1 < (0xe0&0x7f)){
-                      /* output 1 shifted byte */
-			if (iso2022jp_f && !x0201_f) {
-			    (*oconv)(GETA1, GETA2);
-			    NEXT;
-			} else {
-			    c2 = JIS_X_0201;
-			    SEND;
-			}
-                    } else {
-                        /* look like bogus code */
-                        NEXT;
-                    }
-                } else if (input_mode == JIS_X_0208 || input_mode == JIS_X_0212 ||
+		    }
+		    else {
+			/* already established */
+			MORE;
+		    }
+		}
+	    } else if (SP < c1 && c1 < DEL) {
+		/* in case of Roman characters */
+		if (shift_mode) {
+		    /* output 1 shifted byte */
+		    if (iso8859_f) {
+			c2 = ISO_8859_1;
+			SEND;
+		    } else if (nkf_byte_jisx0201_katakana_p(c1)){
+			/* output 1 shifted byte */
+			c2 = JIS_X_0201_1976_K;
+			SEND;
+		    } else {
+			/* look like bogus code */
+			SKIP;
+		    }
+		} else if (input_mode == JIS_X_0208 || input_mode == JIS_X_0212 ||
 			   input_mode == JIS_X_0213_1 || input_mode == JIS_X_0213_2) {
-                    /* in case of Kanji shifted */
-                    c2 = c1;
-                    NEXT;
-                } else if (c1 == '=' && mime_f && !mime_decode_mode) {
-                    /* Check MIME code */
-                    if ((c1 = (*i_getc)(f)) == EOF) {
-                        (*oconv)(0, '=');
-                        LAST;
-                    } else if (c1 == '?') {
-                        /* =? is mime conversion start sequence */
+		    /* in case of Kanji shifted */
+		    MORE;
+		} else if (c1 == '=' && mime_f && !mime_decode_mode) {
+		    /* Check MIME code */
+		    if ((c1 = (*i_getc)(f)) == EOF) {
+			(*oconv)(0, '=');
+			LAST;
+		    } else if (c1 == '?') {
+			/* =? is mime conversion start sequence */
 			if(mime_f == STRICT_MIME) {
 			    /* check in real detail */
 			    if (mime_begin_strict(f) == EOF)
 				LAST;
-			    else
-				NEXT;
+			    SKIP;
 			} else if (mime_begin(f) == EOF)
-                            LAST;
-                        else
-                            NEXT;
-                    } else {
-                        (*oconv)(0, '=');
-                        (*i_ungetc)(c1,f);
-                        NEXT;
-                    }
-                } else {
-                    /* normal ASCII code */
-                    SEND;
-                }
-            } else if (c1 == SI && (!is_8bit || mime_decode_mode)) {
-                shift_mode = FALSE;
-                NEXT;
-            } else if (c1 == SO && (!is_8bit || mime_decode_mode)) {
-                shift_mode = TRUE;
-                NEXT;
-            } else if (c1 == ESC && (!is_8bit || mime_decode_mode)) {
-                if ((c1 = (*i_getc)(f)) == EOF) {
-                    /*  (*oconv)(0, ESC); don't send bogus code */
-                    LAST;
-                } else if (c1 == '$') {
-                    if ((c1 = (*i_getc)(f)) == EOF) {
-                        /*
-                        (*oconv)(0, ESC); don't send bogus code
-                        (*oconv)(0, '$'); */
-                        LAST;
-                    } else if (c1 == '@'|| c1 == 'B') {
-                        /* This is kanji introduction */
-                        input_mode = JIS_X_0208;
-                        shift_mode = FALSE;
-                        set_input_codename("ISO-2022-JP");
-#ifdef CHECK_OPTION
-                        debug("ISO-2022-JP");
-#endif
-                        NEXT;
-                    } else if (c1 == '(') {
-                        if ((c1 = (*i_getc)(f)) == EOF) {
-                            /* don't send bogus code
-                            (*oconv)(0, ESC);
-                            (*oconv)(0, '$');
-                            (*oconv)(0, '(');
-                                */
-                            LAST;
-                        } else if (c1 == '@'|| c1 == 'B') {
-                            /* This is kanji introduction */
-                            input_mode = JIS_X_0208;
-                            shift_mode = FALSE;
-                            NEXT;
+			    LAST;
+			SKIP;
+		    } else {
+			(*oconv)(0, '=');
+			(*i_ungetc)(c1,f);
+			SKIP;
+		    }
+		} else {
+		    /* normal ASCII code */
+		    SEND;
+		}
+	    } else if (c1 == SI && (!is_8bit || mime_decode_mode)) {
+		shift_mode = 0;
+		SKIP;
+	    } else if (c1 == SO && (!is_8bit || mime_decode_mode)) {
+		shift_mode = 1;
+		SKIP;
+	    } else if (c1 == ESC && (!is_8bit || mime_decode_mode)) {
+		if ((c1 = (*i_getc)(f)) == EOF) {
+		    /*  (*oconv)(0, ESC); don't send bogus code */
+		    LAST;
+		}
+		else if (c1 == '&') {
+		    /* IRR */
+		    if ((c1 = (*i_getc)(f)) == EOF) {
+			LAST;
+		    } else {
+			SKIP;
+		    }
+		}
+		else if (c1 == '$') {
+		    /* GZDMx */
+		    if ((c1 = (*i_getc)(f)) == EOF) {
+			/* don't send bogus code
+			   (*oconv)(0, ESC);
+			   (*oconv)(0, '$'); */
+			LAST;
+		    } else if (c1 == '@' || c1 == 'B') {
+			/* JIS X 0208 */
+			set_input_mode(JIS_X_0208);
+			SKIP;
+		    } else if (c1 == '(') {
+			/* GZDM4 */
+			if ((c1 = (*i_getc)(f)) == EOF) {
+			    /* don't send bogus code
+			       (*oconv)(0, ESC);
+			       (*oconv)(0, '$');
+			       (*oconv)(0, '(');
+			     */
+			    LAST;
+			} else if (c1 == '@'|| c1 == 'B') {
+			    /* JIS X 0208 */
+			    set_input_mode(JIS_X_0208);
+			    SKIP;
 #ifdef X0212_ENABLE
-                        } else if (c1 == 'D'){
-                            input_mode = JIS_X_0212;
-                            shift_mode = FALSE;
-                            NEXT;
+			} else if (c1 == 'D'){
+			    set_input_mode(JIS_X_0212);
+			    SKIP;
 #endif /* X0212_ENABLE */
-                        } else if (c1 == 0x4F){
-                            input_mode = JIS_X_0213_1;
-                            shift_mode = FALSE;
-                            NEXT;
-                        } else if (c1 == 0x50){
-                            input_mode = JIS_X_0213_2;
-                            shift_mode = FALSE;
-                            NEXT;
-                        } else {
-                            /* could be some special code */
-                            (*oconv)(0, ESC);
-                            (*oconv)(0, '$');
-                            (*oconv)(0, '(');
-                            (*oconv)(0, c1);
-                            NEXT;
-                        }
-                    } else if (broken_f&0x2) {
-                        /* accept any ESC-(-x as broken code ... */
-                        input_mode = JIS_X_0208;
-                        shift_mode = FALSE;
-                        NEXT;
-                    } else {
-                        (*oconv)(0, ESC);
-                        (*oconv)(0, '$');
-                        (*oconv)(0, c1);
-                        NEXT;
-                    }
-                } else if (c1 == '(') {
-                    if ((c1 = (*i_getc)(f)) == EOF) {
-                        /* don't send bogus code
-                        (*oconv)(0, ESC);
-                        (*oconv)(0, '('); */
-                        LAST;
-                    } else {
-                        if (c1 == 'I') {
-                            /* This is X0201 kana introduction */
-                            input_mode = JIS_X_0201; shift_mode = JIS_X_0201;
-                            NEXT;
-                        } else if (c1 == 'B' || c1 == 'J' || c1 == 'H') {
-                            /* This is X0208 kanji introduction */
-                            input_mode = ASCII; shift_mode = FALSE;
-                            NEXT;
-                        } else if (broken_f&0x2) {
-                            input_mode = ASCII; shift_mode = FALSE;
-                            NEXT;
-                        } else {
-                            (*oconv)(0, ESC);
-                            (*oconv)(0, '(');
-                            /* maintain various input_mode here */
-                            SEND;
-                        }
-                    }
-               } else if ( c1 == 'N' || c1 == 'n'){
-                   /* SS2 */
-                   c3 = (*i_getc)(f);  /* skip SS2 */
-                   if ( (SP<=c3 && c3 < 0x60) || (0xa0<=c3 && c3 < 0xe0)){
-                       c1 = c3;
-                       c2 = JIS_X_0201;
-                       SEND;
-                   }else{
-                       (*i_ungetc)(c3, f);
-                       /* lonely ESC  */
-                       (*oconv)(0, ESC);
-                       SEND;
-                   }
-                } else {
-                    /* lonely ESC  */
-                    (*oconv)(0, ESC);
-                    SEND;
-                }
+			} else if (c1 == 'O' || c1 == 'Q'){
+			    set_input_mode(JIS_X_0213_1);
+			    SKIP;
+			} else if (c1 == 'P'){
+			    set_input_mode(JIS_X_0213_2);
+			    SKIP;
+			} else {
+			    /* could be some special code */
+			    (*oconv)(0, ESC);
+			    (*oconv)(0, '$');
+			    (*oconv)(0, '(');
+			    (*oconv)(0, c1);
+			    SKIP;
+			}
+		    } else if (broken_f&0x2) {
+			/* accept any ESC-(-x as broken code ... */
+			input_mode = JIS_X_0208;
+			shift_mode = 0;
+			SKIP;
+		    } else {
+			(*oconv)(0, ESC);
+			(*oconv)(0, '$');
+			(*oconv)(0, c1);
+			SKIP;
+		    }
+		} else if (c1 == '(') {
+		    /* GZD4 */
+		    if ((c1 = (*i_getc)(f)) == EOF) {
+			/* don't send bogus code
+			   (*oconv)(0, ESC);
+			   (*oconv)(0, '('); */
+			LAST;
+		    }
+		    else if (c1 == 'I') {
+			/* JIS X 0201 Katakana */
+			set_input_mode(JIS_X_0201_1976_K);
+			SKIP;
+		    }
+		    else if (c1 == 'B' || c1 == 'J' || c1 == 'H') {
+			/* ISO-646IRV:1983 or JIS X 0201 Roman or JUNET */
+			set_input_mode(ASCII);
+			SKIP;
+		    }
+		    else if (broken_f&0x2) {
+			set_input_mode(ASCII);
+			SKIP;
+		    }
+		    else {
+			(*oconv)(0, ESC);
+			(*oconv)(0, '(');
+			SEND;
+		    }
+		}
+		else if (c1 == '.') {
+		    /* G2D6 */
+		    if ((c1 = (*i_getc)(f)) == EOF) {
+			LAST;
+		    }
+		    else if (c1 == 'A') {
+			/* ISO-8859-1 */
+			g2 = ISO_8859_1;
+			SKIP;
+		    }
+		    else {
+			(*oconv)(0, ESC);
+			(*oconv)(0, '.');
+			SEND;
+		    }
+		}
+		else if (c1 == 'N') {
+		    /* SS2 */
+		    c1 = (*i_getc)(f);
+		    if (g2 == ISO_8859_1) {
+			c2 = ISO_8859_1;
+			SEND;
+		    }else{
+			(*i_ungetc)(c1, f);
+			/* lonely ESC  */
+			(*oconv)(0, ESC);
+			SEND;
+		    }
+		}
+		else {
+		    /* lonely ESC  */
+		    (*oconv)(0, ESC);
+		    SEND;
+		}
 	    } else if (c1 == ESC && iconv == s_iconv) {
 		/* ESC in Shift_JIS */
 		if ((c1 = (*i_getc)(f)) == EOF) {
@@ -5403,32 +5540,33 @@
 		} else if (c1 == '$') {
 		    /* J-PHONE emoji */
 		    if ((c1 = (*i_getc)(f)) == EOF) {
+			LAST;
+		    } else if (('E' <= c1 && c1 <= 'G') ||
+			       ('O' <= c1 && c1 <= 'Q')) {
 			/*
-			   (*oconv)(0, ESC); don't send bogus code
-			   (*oconv)(0, '$'); */
-			LAST;
-		    } else {
-			if (('E' <= c1 && c1 <= 'G') ||
-			    ('O' <= c1 && c1 <= 'Q')) {
-			    /*
-			       NUM : 0 1 2 3 4 5
-			       BYTE: G E F O P Q
-			       C%7 : 1 6 0 2 3 4
-			       C%7 : 0 1 2 3 4 5 6
-			       NUM : 2 0 3 4 5 X 1
-			     */
-			    static const char jphone_emoji_first_table[7] = {2, 0, 3, 4, 5, 0, 1};
-			    c0 = (jphone_emoji_first_table[c1 % 7] << 8) - SP + 0xE000 + CLASS_UNICODE;
-			    while ((c1 = (*i_getc)(f)) != EOF) {
-				if (SP <= c1 && c1 <= 'z') {
-				    (*oconv)(0, c1 + c0);
-				} else break; /* c1 == SO */
-			    }
+			   NUM : 0 1 2 3 4 5
+			   BYTE: G E F O P Q
+			   C%7 : 1 6 0 2 3 4
+			   C%7 : 0 1 2 3 4 5 6
+			   NUM : 2 0 3 4 5 X 1
+			 */
+			static const int jphone_emoji_first_table[7] =
+			{0xE1E0, 0xDFE0, 0xE2E0, 0xE3E0, 0xE4E0, 0xDFE0, 0xE0E0};
+			c3 = nkf_char_unicode_new(jphone_emoji_first_table[c1 % 7]);
+			if ((c1 = (*i_getc)(f)) == EOF) LAST;
+			while (SP <= c1 && c1 <= 'z') {
+			    (*oconv)(0, c1 + c3);
+			    if ((c1 = (*i_getc)(f)) == EOF) LAST;
 			}
+			SKIP;
 		    }
-		    if (c1 == EOF) LAST;
-		    NEXT;
-		} else {
+		    else {
+			(*oconv)(0, ESC);
+			(*oconv)(0, '$');
+			SEND;
+		    }
+		}
+		else {
 		    /* lonely ESC  */
 		    (*oconv)(0, ESC);
 		    SEND;
@@ -5466,33 +5604,29 @@
 			SEND;
 		    }
 		}
-	    } else if (c1 == DEL && input_mode == JIS_X_0208) {
-		/* CP5022x */
-		c2 = c1;
-		NEXT;
 	    } else
-                SEND;
-        }
-        /* send: */
+		SEND;
+	}
+	/* send: */
 	switch(input_mode){
 	case ASCII:
-	    switch ((*iconv)(c2, c1, c0)) {  /* can be EUC / SJIS / UTF-8 / UTF-16 */
+	    switch ((*iconv)(c2, c1, 0)) {  /* can be EUC / SJIS / UTF-8 */
 	    case -2:
 		/* 4 bytes UTF-8 */
-		if ((c0 = (*i_getc)(f)) != EOF) {
-		    code_status(c0);
-		    c0 <<= 8;
-		    if ((c3 = (*i_getc)(f)) != EOF) {
-			code_status(c3);
-			(*iconv)(c2, c1, c0|c3);
+		if ((c3 = (*i_getc)(f)) != EOF) {
+		    code_status(c3);
+		    c3 <<= 8;
+		    if ((c4 = (*i_getc)(f)) != EOF) {
+			code_status(c4);
+			(*iconv)(c2, c1, c3|c4);
 		    }
 		}
 		break;
 	    case -1:
 		/* 3 bytes EUC or UTF-8 */
-		if ((c0 = (*i_getc)(f)) != EOF) {
-		    code_status(c0);
-		    (*iconv)(c2, c1, c0);
+		if ((c3 = (*i_getc)(f)) != EOF) {
+		    code_status(c3);
+		    (*iconv)(c2, c1, c3);
 		}
 		break;
 	    }
@@ -5503,8 +5637,7 @@
 		0x7F <= c2 && c2 <= 0x92 &&
 		0x21 <= c1 && c1 <= 0x7E) {
 		/* CP932 UDC */
-		if(c1 == 0x7F) return 0;
-		c1 = (c2 - 0x7F) * 94 + c1 - 0x21 + 0xE000 + CLASS_UNICODE;
+		c1 = nkf_char_unicode_new((c2 - 0x7F) * 94 + c1 - 0x21 + 0xE000);
 		c2 = 0;
 	    }
 	    (*oconv)(c2, c1); /* this is JIS, not SJIS/EUC case */
@@ -5521,10 +5654,10 @@
 	    (*oconv)(input_mode, c1);  /* other special case */
 	}
 
-        c2 = 0;
-        c0 = 0;
-        continue;
-        /* goto next_word */
+	c2 = 0;
+	c3 = 0;
+	continue;
+	/* goto next_word */
     }
 
     /* epilogue */
@@ -5544,19 +5677,26 @@
 #endif
 	}
     }
-    return 1;
+    return 0;
 }
 
-void options(unsigned char *cp)
+/*
+ * int options(unsigned char *cp)
+ * 
+ * return values:
+ *    0: success
+ *   -1: ArgumentError
+ */
+static int
+options(unsigned char *cp)
 {
     nkf_char i, j;
     unsigned char *p;
     unsigned char *cp_back = NULL;
-    char codeset[32];
     nkf_encoding *enc;
 
     if (option_mode==1)
-	return;
+	return 0;
     while(*cp && *cp++!='-');
     while (*cp || cp_back) {
 	if(!*cp){
@@ -5565,188 +5705,188 @@
 	    continue;
 	}
 	p = 0;
-        switch (*cp++) {
-        case '-':  /* literal options */
+	switch (*cp++) {
+	case '-':  /* literal options */
 	    if (!*cp || *cp == SP) {        /* ignore the rest of arguments */
 		option_mode = 1;
-		return;
+		return 0;
 	    }
-            for (i=0;i<sizeof(long_option)/sizeof(long_option[0]);i++) {
-                p = (unsigned char *)long_option[i].name;
-                for (j=0;*p && *p != '=' && *p == cp[j];p++, j++);
+	    for (i=0;i<sizeof(long_option)/sizeof(long_option[0]);i++) {
+		p = (unsigned char *)long_option[i].name;
+		for (j=0;*p && *p != '=' && *p == cp[j];p++, j++);
 		if (*p == cp[j] || cp[j] == SP){
 		    p = &cp[j] + 1;
 		    break;
 		}
 		p = 0;
-            }
+	    }
 	    if (p == 0) {
+#if !defined(PERL_XS) && !defined(WIN32DLL)
 		fprintf(stderr, "unknown long option: --%s\n", cp);
-		return;
+#endif
+		return -1;
 	    }
 	    while(*cp && *cp != SP && cp++);
-            if (long_option[i].alias[0]){
+	    if (long_option[i].alias[0]){
 		cp_back = cp;
 		cp = (unsigned char *)long_option[i].alias;
 	    }else{
-                if (strcmp(long_option[i].name, "ic=") == 0){
-		    nkf_str_upcase((char *)p, codeset, 32);
-		    enc = nkf_enc_find(codeset);
+		if (strcmp(long_option[i].name, "ic=") == 0){
+		    enc = nkf_enc_find((char *)p);
 		    if (!enc) continue;
 		    input_encoding = enc;
-                    continue;
+		    continue;
 		}
-                if (strcmp(long_option[i].name, "oc=") == 0){
-		    nkf_str_upcase((char *)p, codeset, 32);
-		    enc = nkf_enc_find(codeset);
-		    if (enc == 0) continue;
+		if (strcmp(long_option[i].name, "oc=") == 0){
+		    enc = nkf_enc_find((char *)p);
+		    if (enc <= 0) continue;
 		    output_encoding = enc;
-                    continue;
+		    continue;
 		}
-                if (strcmp(long_option[i].name, "guess=") == 0){
+		if (strcmp(long_option[i].name, "guess=") == 0){
 		    if (p[0] == '0' || p[0] == '1') {
 			guess_f = 1;
 		    } else {
 			guess_f = 2;
 		    }
-                    continue;
-                }
+		    continue;
+		}
 #ifdef OVERWRITE
-                if (strcmp(long_option[i].name, "overwrite") == 0){
-                    file_out_f = TRUE;
-                    overwrite_f = TRUE;
+		if (strcmp(long_option[i].name, "overwrite") == 0){
+		    file_out_f = TRUE;
+		    overwrite_f = TRUE;
 		    preserve_time_f = TRUE;
-                    continue;
-                }
-                if (strcmp(long_option[i].name, "overwrite=") == 0){
-                    file_out_f = TRUE;
-                    overwrite_f = TRUE;
+		    continue;
+		}
+		if (strcmp(long_option[i].name, "overwrite=") == 0){
+		    file_out_f = TRUE;
+		    overwrite_f = TRUE;
 		    preserve_time_f = TRUE;
 		    backup_f = TRUE;
 		    backup_suffix = malloc(strlen((char *) p) + 1);
 		    strcpy(backup_suffix, (char *) p);
-                    continue;
-                }
-                if (strcmp(long_option[i].name, "in-place") == 0){
-                    file_out_f = TRUE;
-                    overwrite_f = TRUE;
+		    continue;
+		}
+		if (strcmp(long_option[i].name, "in-place") == 0){
+		    file_out_f = TRUE;
+		    overwrite_f = TRUE;
 		    preserve_time_f = FALSE;
 		    continue;
-                }
-                if (strcmp(long_option[i].name, "in-place=") == 0){
-                    file_out_f = TRUE;
-                    overwrite_f = TRUE;
+		}
+		if (strcmp(long_option[i].name, "in-place=") == 0){
+		    file_out_f = TRUE;
+		    overwrite_f = TRUE;
 		    preserve_time_f = FALSE;
 		    backup_f = TRUE;
 		    backup_suffix = malloc(strlen((char *) p) + 1);
 		    strcpy(backup_suffix, (char *) p);
 		    continue;
-                }
+		}
 #endif
 #ifdef INPUT_OPTION
-                if (strcmp(long_option[i].name, "cap-input") == 0){
-                    cap_f = TRUE;
-                    continue;
-                }
-                if (strcmp(long_option[i].name, "url-input") == 0){
-                    url_f = TRUE;
-                    continue;
-                }
+		if (strcmp(long_option[i].name, "cap-input") == 0){
+		    cap_f = TRUE;
+		    continue;
+		}
+		if (strcmp(long_option[i].name, "url-input") == 0){
+		    url_f = TRUE;
+		    continue;
+		}
 #endif
 #ifdef NUMCHAR_OPTION
-                if (strcmp(long_option[i].name, "numchar-input") == 0){
-                    numchar_f = TRUE;
-                    continue;
-                }
+		if (strcmp(long_option[i].name, "numchar-input") == 0){
+		    numchar_f = TRUE;
+		    continue;
+		}
 #endif
 #ifdef CHECK_OPTION
-                if (strcmp(long_option[i].name, "no-output") == 0){
-                    noout_f = TRUE;
-                    continue;
-                }
-                if (strcmp(long_option[i].name, "debug") == 0){
-                    debug_f = TRUE;
-                    continue;
-                }
+		if (strcmp(long_option[i].name, "no-output") == 0){
+		    noout_f = TRUE;
+		    continue;
+		}
+		if (strcmp(long_option[i].name, "debug") == 0){
+		    debug_f = TRUE;
+		    continue;
+		}
 #endif
-                if (strcmp(long_option[i].name, "cp932") == 0){
+		if (strcmp(long_option[i].name, "cp932") == 0){
 #ifdef SHIFTJIS_CP932
-                    cp51932_f = TRUE;
-                    cp932inv_f = -TRUE;
+		    cp51932_f = TRUE;
+		    cp932inv_f = -TRUE;
 #endif
 #ifdef UTF8_OUTPUT_ENABLE
-                    ms_ucs_map_f = UCS_MAP_CP932;
+		    ms_ucs_map_f = UCS_MAP_CP932;
 #endif
-                    continue;
-                }
-                if (strcmp(long_option[i].name, "no-cp932") == 0){
+		    continue;
+		}
+		if (strcmp(long_option[i].name, "no-cp932") == 0){
 #ifdef SHIFTJIS_CP932
-                    cp51932_f = FALSE;
-                    cp932inv_f = FALSE;
+		    cp51932_f = FALSE;
+		    cp932inv_f = FALSE;
 #endif
 #ifdef UTF8_OUTPUT_ENABLE
-                    ms_ucs_map_f = UCS_MAP_ASCII;
+		    ms_ucs_map_f = UCS_MAP_ASCII;
 #endif
-                    continue;
-                }
+		    continue;
+		}
 #ifdef SHIFTJIS_CP932
-                if (strcmp(long_option[i].name, "cp932inv") == 0){
-                    cp932inv_f = -TRUE;
-                    continue;
-                }
+		if (strcmp(long_option[i].name, "cp932inv") == 0){
+		    cp932inv_f = -TRUE;
+		    continue;
+		}
 #endif
 
 #ifdef X0212_ENABLE
-                if (strcmp(long_option[i].name, "x0212") == 0){
-                    x0212_f = TRUE;
-                    continue;
-                }
+		if (strcmp(long_option[i].name, "x0212") == 0){
+		    x0212_f = TRUE;
+		    continue;
+		}
 #endif
 
 #ifdef EXEC_IO
-                  if (strcmp(long_option[i].name, "exec-in") == 0){
-                      exec_f = 1;
-                      return;
-                  }
-                  if (strcmp(long_option[i].name, "exec-out") == 0){
-                      exec_f = -1;
-                      return;
-                  }
+		if (strcmp(long_option[i].name, "exec-in") == 0){
+		    exec_f = 1;
+		    return 0;
+		}
+		if (strcmp(long_option[i].name, "exec-out") == 0){
+		    exec_f = -1;
+		    return 0;
+		}
 #endif
 #if defined(UTF8_OUTPUT_ENABLE) && defined(UTF8_INPUT_ENABLE)
-                if (strcmp(long_option[i].name, "no-cp932ext") == 0){
+		if (strcmp(long_option[i].name, "no-cp932ext") == 0){
 		    no_cp932ext_f = TRUE;
-                    continue;
-                }
+		    continue;
+		}
 		if (strcmp(long_option[i].name, "no-best-fit-chars") == 0){
 		    no_best_fit_chars_f = TRUE;
 		    continue;
 		}
-                if (strcmp(long_option[i].name, "fb-skip") == 0){
+		if (strcmp(long_option[i].name, "fb-skip") == 0){
 		    encode_fallback = NULL;
-                    continue;
-                }
-                if (strcmp(long_option[i].name, "fb-html") == 0){
+		    continue;
+		}
+		if (strcmp(long_option[i].name, "fb-html") == 0){
 		    encode_fallback = encode_fallback_html;
-                    continue;
-                }
-                if (strcmp(long_option[i].name, "fb-xml") == 0){
+		    continue;
+		}
+		if (strcmp(long_option[i].name, "fb-xml") == 0){
 		    encode_fallback = encode_fallback_xml;
-                    continue;
-                }
-                if (strcmp(long_option[i].name, "fb-java") == 0){
+		    continue;
+		}
+		if (strcmp(long_option[i].name, "fb-java") == 0){
 		    encode_fallback = encode_fallback_java;
-                    continue;
-                }
-                if (strcmp(long_option[i].name, "fb-perl") == 0){
+		    continue;
+		}
+		if (strcmp(long_option[i].name, "fb-perl") == 0){
 		    encode_fallback = encode_fallback_perl;
-                    continue;
-                }
-                if (strcmp(long_option[i].name, "fb-subchar") == 0){
+		    continue;
+		}
+		if (strcmp(long_option[i].name, "fb-subchar") == 0){
 		    encode_fallback = encode_fallback_subchar;
-                    continue;
-                }
-                if (strcmp(long_option[i].name, "fb-subchar=") == 0){
+		    continue;
+		}
+		if (strcmp(long_option[i].name, "fb-subchar=") == 0){
 		    encode_fallback = encode_fallback_subchar;
 		    unicode_subchar = 0;
 		    if (p[0] != '0'){
@@ -5770,14 +5910,14 @@
 		    }
 		    w16e_conv(unicode_subchar, &i, &j);
 		    unicode_subchar = i<<8 | j;
-                    continue;
-                }
+		    continue;
+		}
 #endif
 #ifdef UTF8_OUTPUT_ENABLE
-                if (strcmp(long_option[i].name, "ms-ucs-map") == 0){
-                    ms_ucs_map_f = UCS_MAP_MS;
-                    continue;
-                }
+		if (strcmp(long_option[i].name, "ms-ucs-map") == 0){
+		    ms_ucs_map_f = UCS_MAP_MS;
+		    continue;
+		}
 #endif
 #ifdef UNICODE_NORMALIZATION
 		if (strcmp(long_option[i].name, "utf8mac-input") == 0){
@@ -5785,24 +5925,28 @@
 		    continue;
 		}
 #endif
-                if (strcmp(long_option[i].name, "prefix=") == 0){
-                    if (nkf_isgraph(p[0])){
-                        for (i = 1; nkf_isgraph(p[i]); i++){
-                            prefix_table[p[i]] = p[0];
-                        }
-                    }
-                    continue;
-                }
-            }
-            continue;
-        case 'b':           /* buffered mode */
-            unbuf_f = FALSE;
-            continue;
-        case 'u':           /* non bufferd mode */
-            unbuf_f = TRUE;
-            continue;
-        case 't':           /* transparent mode */
-            if (*cp=='1') {
+		if (strcmp(long_option[i].name, "prefix=") == 0){
+		    if (nkf_isgraph(p[0])){
+			for (i = 1; nkf_isgraph(p[i]); i++){
+			    prefix_table[p[i]] = p[0];
+			}
+		    }
+		    continue;
+		}
+#if !defined(PERL_XS) && !defined(WIN32DLL)
+		fprintf(stderr, "unsupported long option: --%s\n", long_option[i].name);
+#endif
+		return -1;
+	    }
+	    continue;
+	case 'b':           /* buffered mode */
+	    unbuf_f = FALSE;
+	    continue;
+	case 'u':           /* non bufferd mode */
+	    unbuf_f = TRUE;
+	    continue;
+	case 't':           /* transparent mode */
+	    if (*cp=='1') {
 		/* alias of -t */
 		cp++;
 		nop_f = TRUE;
@@ -5815,62 +5959,62 @@
 		 */
 		cp++;
 		nop_f = 2;
-            } else
+	    } else
 		nop_f = TRUE;
-            continue;
-        case 'j':           /* JIS output */
-        case 'n':
-            output_encoding = nkf_enc_from_index(ISO_2022_JP);
-            continue;
-        case 'e':           /* AT&T EUC output */
-            output_encoding = nkf_enc_from_index(EUC_JP);
-            continue;
-        case 's':           /* SJIS output */
-            output_encoding = nkf_enc_from_index(WINDOWS_31J);
-            continue;
-        case 'l':           /* ISO8859 Latin-1 support, no conversion */
-            iso8859_f = TRUE;  /* Only compatible with ISO-2022-JP */
-            input_encoding = nkf_enc_from_index(ISO_8859_1);
-            continue;
-        case 'i':           /* Kanji IN ESC-$-@/B */
-            if (*cp=='@'||*cp=='B')
-                kanji_intro = *cp++;
-            continue;
-        case 'o':           /* ASCII IN ESC-(-J/B */
-            if (*cp=='J'||*cp=='B'||*cp=='H')
-                ascii_intro = *cp++;
-            continue;
-        case 'h':
-            /*
-                bit:1   katakana->hiragana
-                bit:2   hiragana->katakana
-            */
-            if ('9'>= *cp && *cp>='0')
-                hira_f |= (*cp++ -'0');
-            else
-                hira_f |= 1;
-            continue;
-        case 'r':
-            rot_f = TRUE;
-            continue;
+	    continue;
+	case 'j':           /* JIS output */
+	case 'n':
+	    output_encoding = nkf_enc_from_index(ISO_2022_JP);
+	    continue;
+	case 'e':           /* AT&T EUC output */
+	    output_encoding = nkf_enc_from_index(EUCJP_NKF);
+	    continue;
+	case 's':           /* SJIS output */
+	    output_encoding = nkf_enc_from_index(WINDOWS_31J);
+	    continue;
+	case 'l':           /* ISO8859 Latin-1 support, no conversion */
+	    iso8859_f = TRUE;  /* Only compatible with ISO-2022-JP */
+	    input_encoding = nkf_enc_from_index(ISO_8859_1);
+	    continue;
+	case 'i':           /* Kanji IN ESC-$-@/B */
+	    if (*cp=='@'||*cp=='B')
+		kanji_intro = *cp++;
+	    continue;
+	case 'o':           /* ASCII IN ESC-(-J/B */
+	    if (*cp=='J'||*cp=='B'||*cp=='H')
+		ascii_intro = *cp++;
+	    continue;
+	case 'h':
+	    /*
+	       bit:1   katakana->hiragana
+	       bit:2   hiragana->katakana
+	     */
+	    if ('9'>= *cp && *cp>='0')
+		hira_f |= (*cp++ -'0');
+	    else
+		hira_f |= 1;
+	    continue;
+	case 'r':
+	    rot_f = TRUE;
+	    continue;
 #if defined(MSDOS) || defined(__OS2__)
-        case 'T':
-            binmode_f = FALSE;
-            continue;
+	case 'T':
+	    binmode_f = FALSE;
+	    continue;
 #endif
 #ifndef PERL_XS
-        case 'V':
-            show_configuration();
-            exit(1);
-            break;
-        case 'v':
-            usage();
-            exit(1);
-            break;
+	case 'V':
+	    show_configuration();
+	    exit(1);
+	    break;
+	case 'v':
+	    usage();
+	    exit(1);
+	    break;
 #endif
 #ifdef UTF8_OUTPUT_ENABLE
-        case 'w':           /* UTF-8 output */
-            if (cp[0] == '8') {
+	case 'w':           /* UTF-8 output */
+	    if (cp[0] == '8') {
 		cp++;
 		if (cp[0] == '0'){
 		    cp++;
@@ -5896,10 +6040,10 @@
 		    output_endian = ENDIAN_LITTLE;
 		} else if (cp[0] == 'B') {
 		    cp++;
-                } else {
+		} else {
 		    output_encoding = nkf_enc_from_index(enc_idx);
 		    continue;
-                }
+		}
 		if (cp[0] == '0'){
 		    cp++;
 		    enc_idx = enc_idx == UTF_16
@@ -5913,10 +6057,10 @@
 		}
 		output_encoding = nkf_enc_from_index(enc_idx);
 	    }
-            continue;
+	    continue;
 #endif
 #ifdef UTF8_INPUT_ENABLE
-        case 'W':           /* UTF input */
+	case 'W':           /* UTF input */
 	    if (cp[0] == '8') {
 		cp++;
 		input_encoding = nkf_enc_from_index(UTF_8);
@@ -5946,58 +6090,58 @@
 		    : (output_endian == ENDIAN_LITTLE ? UTF_32LE : UTF_32BE);
 		input_encoding = nkf_enc_from_index(enc_idx);
 	    }
-            continue;
+	    continue;
 #endif
-        /* Input code assumption */
+	    /* Input code assumption */
 	case 'J':   /* ISO-2022-JP input */
 	    input_encoding = nkf_enc_from_index(ISO_2022_JP);
 	    continue;
 	case 'E':   /* EUC-JP input */
-	    input_encoding = nkf_enc_from_index(EUC_JP);
+	    input_encoding = nkf_enc_from_index(EUCJP_NKF);
 	    continue;
 	case 'S':   /* Windows-31J input */
 	    input_encoding = nkf_enc_from_index(WINDOWS_31J);
 	    continue;
-        case 'Z':   /* Convert X0208 alphabet to asii */
-            /* alpha_f
+	case 'Z':   /* Convert X0208 alphabet to asii */
+	    /* alpha_f
 	       bit:0   Convert JIS X 0208 Alphabet to ASCII
 	       bit:1   Convert Kankaku to one space
 	       bit:2   Convert Kankaku to two spaces
 	       bit:3   Convert HTML Entity
 	       bit:4   Convert JIS X 0208 Katakana to JIS X 0201 Katakana
-            */
+	     */
 	    while ('0'<= *cp && *cp <='9') {
 		alpha_f |= 1 << (*cp++ - '0');
 	    }
-            if (!alpha_f) alpha_f = 1;
-            continue;
-        case 'x':   /* Convert X0201 kana to X0208 or X0201 Conversion */
-            x0201_f = FALSE;    /* No X0201->X0208 conversion */
-            /* accept  X0201
-                    ESC-(-I     in JIS, EUC, MS Kanji
-                    SI/SO       in JIS, EUC, MS Kanji
-                    SSO         in EUC, JIS, not in MS Kanji
-                    MS Kanji (0xa0-0xdf)
-               output  X0201
-                    ESC-(-I     in JIS (0x20-0x5f)
-                    SSO         in EUC (0xa0-0xdf)
-                    0xa0-0xd    in MS Kanji (0xa0-0xdf)
-            */
-            continue;
-        case 'X':   /* Convert X0201 kana to X0208 */
-            x0201_f = TRUE;
-            continue;
-        case 'F':   /* prserve new lines */
+	    if (!alpha_f) alpha_f = 1;
+	    continue;
+	case 'x':   /* Convert X0201 kana to X0208 or X0201 Conversion */
+	    x0201_f = FALSE;    /* No X0201->X0208 conversion */
+	    /* accept  X0201
+	       ESC-(-I     in JIS, EUC, MS Kanji
+	       SI/SO       in JIS, EUC, MS Kanji
+	       SS2         in EUC, JIS, not in MS Kanji
+	       MS Kanji (0xa0-0xdf)
+	       output  X0201
+	       ESC-(-I     in JIS (0x20-0x5f)
+	       SS2         in EUC (0xa0-0xdf)
+	       0xa0-0xd    in MS Kanji (0xa0-0xdf)
+	     */
+	    continue;
+	case 'X':   /* Convert X0201 kana to X0208 */
+	    x0201_f = TRUE;
+	    continue;
+	case 'F':   /* prserve new lines */
 	    fold_preserve_f = TRUE;
-        case 'f':   /* folding -f60 or -f */
-            fold_f = TRUE;
-            fold_len = 0;
-            while('0'<= *cp && *cp <='9') { /* we don't use atoi here */
+	case 'f':   /* folding -f60 or -f */
+	    fold_f = TRUE;
+	    fold_len = 0;
+	    while('0'<= *cp && *cp <='9') { /* we don't use atoi here */
 		fold_len *= 10;
 		fold_len += *cp++ - '0';
 	    }
-            if (!(0<fold_len && fold_len<BUFSIZ))
-                fold_len = DEFAULT_FOLD;
+	    if (!(0<fold_len && fold_len<BUFSIZ))
+		fold_len = DEFAULT_FOLD;
 	    if (*cp=='-') {
 		fold_margin = 0;
 		cp++;
@@ -6006,99 +6150,103 @@
 		    fold_margin += *cp++ - '0';
 		}
 	    }
-            continue;
-        case 'm':   /* MIME support */
-            /* mime_decode_f = TRUE; */ /* this has too large side effects... */
-            if (*cp=='B'||*cp=='Q') {
-                mime_decode_mode = *cp++;
-                mimebuf_f = FIXED_MIME;
-            } else if (*cp=='N') {
-                mime_f = TRUE; cp++;
-            } else if (*cp=='S') {
-                mime_f = STRICT_MIME; cp++;
-            } else if (*cp=='0') {
-                mime_decode_f = FALSE;
-                mime_f = FALSE; cp++;
-            } else {
-                mime_f = STRICT_MIME;
-            }
-            continue;
-        case 'M':   /* MIME output */
-            if (*cp=='B') {
-                mimeout_mode = 'B';
-                mimeout_f = FIXED_MIME; cp++;
-            } else if (*cp=='Q') {
-                mimeout_mode = 'Q';
-                mimeout_f = FIXED_MIME; cp++;
-            } else {
+	    continue;
+	case 'm':   /* MIME support */
+	    /* mime_decode_f = TRUE; */ /* this has too large side effects... */
+	    if (*cp=='B'||*cp=='Q') {
+		mime_decode_mode = *cp++;
+		mimebuf_f = FIXED_MIME;
+	    } else if (*cp=='N') {
+		mime_f = TRUE; cp++;
+	    } else if (*cp=='S') {
+		mime_f = STRICT_MIME; cp++;
+	    } else if (*cp=='0') {
+		mime_decode_f = FALSE;
+		mime_f = FALSE; cp++;
+	    } else {
+		mime_f = STRICT_MIME;
+	    }
+	    continue;
+	case 'M':   /* MIME output */
+	    if (*cp=='B') {
+		mimeout_mode = 'B';
+		mimeout_f = FIXED_MIME; cp++;
+	    } else if (*cp=='Q') {
+		mimeout_mode = 'Q';
+		mimeout_f = FIXED_MIME; cp++;
+	    } else {
 		mimeout_f = TRUE;
 	    }
-            continue;
-        case 'B':   /* Broken JIS support */
-            /*  bit:0   no ESC JIS
-                bit:1   allow any x on ESC-(-x or ESC-$-x
-                bit:2   reset to ascii on NL
-            */
-            if ('9'>= *cp && *cp>='0')
-                broken_f |= 1<<(*cp++ -'0');
-            else
-                broken_f |= TRUE;
-            continue;
+	    continue;
+	case 'B':   /* Broken JIS support */
+	    /*  bit:0   no ESC JIS
+	       bit:1   allow any x on ESC-(-x or ESC-$-x
+	       bit:2   reset to ascii on NL
+	     */
+	    if ('9'>= *cp && *cp>='0')
+		broken_f |= 1<<(*cp++ -'0');
+	    else
+		broken_f |= TRUE;
+	    continue;
 #ifndef PERL_XS
-        case 'O':/* for Output file */
-            file_out_f = TRUE;
-            continue;
+	case 'O':/* for Output file */
+	    file_out_f = TRUE;
+	    continue;
 #endif
-        case 'c':/* add cr code */
-            eolmode_f = CRLF;
-            continue;
-        case 'd':/* delete cr code */
-            eolmode_f = LF;
-            continue;
+	case 'c':/* add cr code */
+	    eolmode_f = CRLF;
+	    continue;
+	case 'd':/* delete cr code */
+	    eolmode_f = LF;
+	    continue;
 	case 'I':   /* ISO-2022-JP output */
 	    iso2022jp_f = TRUE;
 	    continue;
-        case 'L':  /* line mode */
-            if (*cp=='u') {         /* unix */
-                eolmode_f = LF; cp++;
-            } else if (*cp=='m') { /* mac */
-                eolmode_f = CR; cp++;
-            } else if (*cp=='w') { /* windows */
-                eolmode_f = CRLF; cp++;
-            } else if (*cp=='0') { /* no conversion  */
-                eolmode_f = 0; cp++;
-            }
-            continue;
+	case 'L':  /* line mode */
+	    if (*cp=='u') {         /* unix */
+		eolmode_f = LF; cp++;
+	    } else if (*cp=='m') { /* mac */
+		eolmode_f = CR; cp++;
+	    } else if (*cp=='w') { /* windows */
+		eolmode_f = CRLF; cp++;
+	    } else if (*cp=='0') { /* no conversion  */
+		eolmode_f = 0; cp++;
+	    }
+	    continue;
 #ifndef PERL_XS
-        case 'g':
-            if ('2' <= *cp && *cp <= '9') {
-                guess_f = 2;
-                cp++;
-            } else if (*cp == '0' || *cp == '1') {
+	case 'g':
+	    if ('2' <= *cp && *cp <= '9') {
+		guess_f = 2;
+		cp++;
+	    } else if (*cp == '0' || *cp == '1') {
 		guess_f = 1;
-                cp++;
-            } else {
+		cp++;
+	    } else {
 		guess_f = 1;
-            }
-            continue;
+	    }
+	    continue;
 #endif
-        case SP:
-        /* module muliple options in a string are allowed for Perl moudle  */
+	case SP:
+	    /* module muliple options in a string are allowed for Perl moudle  */
 	    while(*cp && *cp++!='-');
-            continue;
-        default:
+	    continue;
+	default:
+#if !defined(PERL_XS) && !defined(WIN32DLL)
 	    fprintf(stderr, "unknown option: -%c\n", *(cp-1));
-            /* bogus option but ignored */
-            continue;
-        }
+#endif
+	    /* bogus option but ignored */
+	    return -1;
+	}
     }
+    return 0;
 }
 
 #ifdef WIN32DLL
 #include "nkf32dll.c"
 #elif defined(PERL_XS)
 #else /* WIN32DLL */
-int main(int argc, char **argv)
+int
+main(int argc, char **argv)
 {
     FILE  *fin;
     unsigned char  *cp;
@@ -6109,37 +6257,38 @@
 #ifdef EASYWIN /*Easy Win */
     _BufferSize.y = 400;/*Set Scroll Buffer Size*/
 #endif
+#ifdef DEFAULT_CODE_LOCALE
     setlocale(LC_CTYPE, "");
-
+#endif
     for (argc--,argv++; (argc > 0) && **argv == '-'; argc--, argv++) {
-        cp = (unsigned char *)*argv;
-        options(cp);
+	cp = (unsigned char *)*argv;
+	options(cp);
 #ifdef EXEC_IO
-        if (exec_f){
-            int fds[2], pid;
-            if (pipe(fds) < 0 || (pid = fork()) < 0){
-                abort();
-            }
-            if (pid == 0){
-                if (exec_f > 0){
-                    close(fds[0]);
-                    dup2(fds[1], 1);
-                }else{
-                    close(fds[1]);
-                    dup2(fds[0], 0);
-                }
-                execvp(argv[1], &argv[1]);
-            }
-            if (exec_f > 0){
-                close(fds[1]);
-                dup2(fds[0], 0);
-            }else{
-                close(fds[0]);
-                dup2(fds[1], 1);
-            }
-            argc = 0;
-            break;
-        }
+	if (exec_f){
+	    int fds[2], pid;
+	    if (pipe(fds) < 0 || (pid = fork()) < 0){
+		abort();
+	    }
+	    if (pid == 0){
+		if (exec_f > 0){
+		    close(fds[0]);
+		    dup2(fds[1], 1);
+		}else{
+		    close(fds[1]);
+		    dup2(fds[0], 0);
+		}
+		execvp(argv[1], &argv[1]);
+	    }
+	    if (exec_f > 0){
+		close(fds[1]);
+		dup2(fds[0], 0);
+	    }else{
+		close(fds[0]);
+		dup2(fds[1], 1);
+	    }
+	    argc = 0;
+	    break;
+	}
 #endif
     }
 
@@ -6164,158 +6313,156 @@
 #ifdef EXEC_IO
 	exec_f = exec_f_back;
 #endif
-#ifdef X0212_ENABLE
 	x0212_f = x0212_f_back;
-#endif
 	x0213_f = x0213_f_back;
     }
 
     if (binmode_f == TRUE)
 #if defined(__OS2__) && (defined(__IBMC__) || defined(__IBMCPP__))
-    if (freopen("","wb",stdout) == NULL)
-        return (-1);
+	if (freopen("","wb",stdout) == NULL)
+	    return (-1);
 #else
     setbinmode(stdout);
 #endif
 
     if (unbuf_f)
-      setbuf(stdout, (char *) NULL);
+	setbuf(stdout, (char *) NULL);
     else
-      setvbuffer(stdout, (char *) stdobuf, IOBUF_SIZE);
+	setvbuffer(stdout, (char *) stdobuf, IOBUF_SIZE);
 
     if (argc == 0) {
-      if (binmode_f == TRUE)
+	if (binmode_f == TRUE)
 #if defined(__OS2__) && (defined(__IBMC__) || defined(__IBMCPP__))
-      if (freopen("","rb",stdin) == NULL) return (-1);
+	    if (freopen("","rb",stdin) == NULL) return (-1);
 #else
-      setbinmode(stdin);
+	setbinmode(stdin);
 #endif
-      setvbuffer(stdin, (char *) stdibuf, IOBUF_SIZE);
-      if (nop_f)
-          noconvert(stdin);
-      else {
-          kanji_convert(stdin);
-          if (guess_f) print_guessed_code(NULL);
-      }
+	setvbuffer(stdin, (char *) stdibuf, IOBUF_SIZE);
+	if (nop_f)
+	    noconvert(stdin);
+	else {
+	    kanji_convert(stdin);
+	    if (guess_f) print_guessed_code(NULL);
+	}
     } else {
-      int nfiles = argc;
+	int nfiles = argc;
 	int is_argument_error = FALSE;
-      while (argc--) {
+	while (argc--) {
 	    input_codename = NULL;
 	    input_eol = 0;
 #ifdef CHECK_OPTION
 	    iconv_for_check = 0;
 #endif
-          if ((fin = fopen((origfname = *argv++), "r")) == NULL) {
+	    if ((fin = fopen((origfname = *argv++), "r")) == NULL) {
 		perror(*(argv-1));
 		is_argument_error = TRUE;
 		continue;
-          } else {
+	    } else {
 #ifdef OVERWRITE
-              int fd = 0;
-              int fd_backup = 0;
+		int fd = 0;
+		int fd_backup = 0;
 #endif
 
-/* reopen file for stdout */
-              if (file_out_f == TRUE) {
+		/* reopen file for stdout */
+		if (file_out_f == TRUE) {
 #ifdef OVERWRITE
-                  if (overwrite_f){
-                      outfname = malloc(strlen(origfname)
-                                        + strlen(".nkftmpXXXXXX")
-                                        + 1);
-                      if (!outfname){
-                          perror(origfname);
-                          return -1;
-                      }
-                      strcpy(outfname, origfname);
+		    if (overwrite_f){
+			outfname = malloc(strlen(origfname)
+					  + strlen(".nkftmpXXXXXX")
+					  + 1);
+			if (!outfname){
+			    perror(origfname);
+			    return -1;
+			}
+			strcpy(outfname, origfname);
 #ifdef MSDOS
-                      {
-                          int i;
-                          for (i = strlen(outfname); i; --i){
-                              if (outfname[i - 1] == '/'
-                                  || outfname[i - 1] == '\\'){
-                                  break;
-                              }
-                          }
-                          outfname[i] = '\0';
-                      }
-                      strcat(outfname, "ntXXXXXX");
-                      mktemp(outfname);
+			{
+			    int i;
+			    for (i = strlen(outfname); i; --i){
+				if (outfname[i - 1] == '/'
+				    || outfname[i - 1] == '\\'){
+				    break;
+				}
+			    }
+			    outfname[i] = '\0';
+			}
+			strcat(outfname, "ntXXXXXX");
+			mktemp(outfname);
 			fd = open(outfname, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL,
-                                S_IREAD | S_IWRITE);
+				  S_IREAD | S_IWRITE);
 #else
-                      strcat(outfname, ".nkftmpXXXXXX");
-                      fd = mkstemp(outfname);
+			strcat(outfname, ".nkftmpXXXXXX");
+			fd = mkstemp(outfname);
 #endif
-                      if (fd < 0
-                          || (fd_backup = dup(fileno(stdout))) < 0
-                          || dup2(fd, fileno(stdout)) < 0
-                          ){
-                          perror(origfname);
-                          return -1;
-                      }
-                  }else
+			if (fd < 0
+			    || (fd_backup = dup(fileno(stdout))) < 0
+			    || dup2(fd, fileno(stdout)) < 0
+			   ){
+			    perror(origfname);
+			    return -1;
+			}
+		    }else
 #endif
-		  if(argc == 1) {
-		      outfname = *argv++;
-		      argc--;
-		  } else {
-		      outfname = "nkf.out";
-		  }
+		    if(argc == 1) {
+			outfname = *argv++;
+			argc--;
+		    } else {
+			outfname = "nkf.out";
+		    }
 
-		  if(freopen(outfname, "w", stdout) == NULL) {
-		      perror (outfname);
-		      return (-1);
-		  }
-                  if (binmode_f == TRUE) {
+		    if(freopen(outfname, "w", stdout) == NULL) {
+			perror (outfname);
+			return (-1);
+		    }
+		    if (binmode_f == TRUE) {
 #if defined(__OS2__) && (defined(__IBMC__) || defined(__IBMCPP__))
-                      if (freopen("","wb",stdout) == NULL)
-                           return (-1);
+			if (freopen("","wb",stdout) == NULL)
+			    return (-1);
 #else
-                      setbinmode(stdout);
+			setbinmode(stdout);
 #endif
-                  }
-              }
-              if (binmode_f == TRUE)
+		    }
+		}
+		if (binmode_f == TRUE)
 #if defined(__OS2__) && (defined(__IBMC__) || defined(__IBMCPP__))
-                 if (freopen("","rb",fin) == NULL)
-                    return (-1);
+		    if (freopen("","rb",fin) == NULL)
+			return (-1);
 #else
-                 setbinmode(fin);
+		setbinmode(fin);
 #endif
-              setvbuffer(fin, (char *) stdibuf, IOBUF_SIZE);
-              if (nop_f)
-                  noconvert(fin);
-              else {
-                  char *filename = NULL;
-                  kanji_convert(fin);
-                  if (nfiles > 1) filename = origfname;
-                  if (guess_f) print_guessed_code(filename);
-              }
-              fclose(fin);
+		setvbuffer(fin, (char *) stdibuf, IOBUF_SIZE);
+		if (nop_f)
+		    noconvert(fin);
+		else {
+		    char *filename = NULL;
+		    kanji_convert(fin);
+		    if (nfiles > 1) filename = origfname;
+		    if (guess_f) print_guessed_code(filename);
+		}
+		fclose(fin);
 #ifdef OVERWRITE
-              if (overwrite_f) {
-                  struct stat     sb;
+		if (overwrite_f) {
+		    struct stat     sb;
 #if defined(MSDOS) && !defined(__MINGW32__) && !defined(__WIN32__) && !defined(__WATCOMC__) && !defined(__EMX__) && !defined(__OS2__) && !defined(__DJGPP__)
-                  time_t tb[2];
+		    time_t tb[2];
 #else
-                  struct utimbuf  tb;
+		    struct utimbuf  tb;
 #endif
 
-                  fflush(stdout);
-                  close(fd);
-                  if (dup2(fd_backup, fileno(stdout)) < 0){
-                      perror("dup2");
-                  }
-                  if (stat(origfname, &sb)) {
-                      fprintf(stderr, "Can't stat %s\n", origfname);
-                  }
-                  /* $B%Q!<%_%C%7%g%s$rI|85(B */
-                  if (chmod(outfname, sb.st_mode)) {
-                      fprintf(stderr, "Can't set permission %s\n", outfname);
-                  }
+		    fflush(stdout);
+		    close(fd);
+		    if (dup2(fd_backup, fileno(stdout)) < 0){
+			perror("dup2");
+		    }
+		    if (stat(origfname, &sb)) {
+			fprintf(stderr, "Can't stat %s\n", origfname);
+		    }
+		    /* $B%Q!<%_%C%7%g%s$rI|85(B */
+		    if (chmod(outfname, sb.st_mode)) {
+			fprintf(stderr, "Can't set permission %s\n", outfname);
+		    }
 
-                  /* $B%?%$%`%9%?%s%W$rI|85(B */
+		    /* $B%?%$%`%9%?%s%W$rI|85(B */
 		    if(preserve_time_f){
 #if defined(MSDOS) && !defined(__MINGW32__) && !defined(__WIN32__) && !defined(__WATCOMC__) && !defined(__EMX__) && !defined(__OS2__) && !defined(__DJGPP__)
 			tb[0] = tb[1] = sb.st_mtime;
@@ -6340,6 +6487,7 @@
 			    fprintf(stderr, "Can't rename %s to %s\n",
 				    origfname, backup_filename);
 			}
+			free(backup_filename);
 		    }else{
 #ifdef MSDOS
 			if (unlink(origfname)){
@@ -6347,27 +6495,27 @@
 			}
 #endif
 		    }
-                  if (rename(outfname, origfname)) {
-                      perror(origfname);
-                      fprintf(stderr, "Can't rename %s to %s\n",
-                              outfname, origfname);
-                  }
-                  free(outfname);
-              }
+		    if (rename(outfname, origfname)) {
+			perror(origfname);
+			fprintf(stderr, "Can't rename %s to %s\n",
+				outfname, origfname);
+		    }
+		    free(outfname);
+		}
 #endif
-          }
-      }
+	    }
+	}
 	if (is_argument_error)
 	    return(-1);
     }
 #ifdef EASYWIN /*Easy Win */
     if (file_out_f == FALSE)
-        scanf("%d",&end_check);
+	scanf("%d",&end_check);
     else
-        fclose(stdout);
+	fclose(stdout);
 #else /* for Other OS */
     if (file_out_f == TRUE)
-        fclose(stdout);
+	fclose(stdout);
 #endif /*Easy Win */
     return (0);
 }

Modified: MacRuby/branches/testing/ext/nkf/nkf.c
===================================================================
--- MacRuby/branches/testing/ext/nkf/nkf.c	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/ext/nkf/nkf.c	2008-06-05 08:33:02 UTC (rev 249)
@@ -3,11 +3,11 @@
  *
  *  original nkf2.x is maintained at http://sourceforge.jp/projects/nkf/
  *
- *  $Id: nkf.c 16149 2008-04-22 12:20:36Z naruse $
+ *  $Id: nkf.c 16493 2008-05-20 13:10:28Z naruse $
  *
  */
 
-#define RUBY_NKF_REVISION "$Revision: 16149 $"
+#define RUBY_NKF_REVISION "$Revision: 16493 $"
 #define RUBY_NKF_VERSION NKF_VERSION " (" NKF_RELEASE_DATE ")"
 
 #include "ruby/ruby.h"
@@ -143,6 +143,15 @@
     nkf_split_options(RSTRING_PTR(opt));
     if (!output_encoding) rb_raise(rb_eArgError, "no output encoding given");
 
+    switch (nkf_enc_to_index(output_encoding)) {
+    case UTF_8_BOM:    output_encoding = nkf_enc_from_index(UTF_8); break;
+    case UTF_16BE_BOM: output_encoding = nkf_enc_from_index(UTF_16BE); break;
+    case UTF_16LE_BOM: output_encoding = nkf_enc_from_index(UTF_16LE); break;
+    case UTF_32BE_BOM: output_encoding = nkf_enc_from_index(UTF_32BE); break;
+    case UTF_32LE_BOM: output_encoding = nkf_enc_from_index(UTF_32LE); break;
+    }
+    output_bom_f = FALSE;
+
     incsize = INCSIZE;
 
     input_ctr = 0;
@@ -480,8 +489,8 @@
     rb_define_const(mNKF, "EUC",	rb_enc_from_encoding(rb_nkf_enc_get("EUC-JP")));
     rb_define_const(mNKF, "SJIS",	rb_enc_from_encoding(rb_nkf_enc_get("Shift_JIS")));
     rb_define_const(mNKF, "UTF8",	rb_enc_from_encoding(rb_utf8_encoding()));
-    rb_define_const(mNKF, "UTF16",	rb_enc_from_encoding(rb_nkf_enc_get("UTF-16")));
-    rb_define_const(mNKF, "UTF32",	rb_enc_from_encoding(rb_nkf_enc_get("UTF-32")));
+    rb_define_const(mNKF, "UTF16",	rb_enc_from_encoding(rb_nkf_enc_get("UTF-16BE")));
+    rb_define_const(mNKF, "UTF32",	rb_enc_from_encoding(rb_nkf_enc_get("UTF-32BE")));
 
     /* Full version string of nkf */
     rb_define_const(mNKF, "VERSION", rb_str_new2(RUBY_NKF_VERSION));

Modified: MacRuby/branches/testing/ext/openssl/ossl_bn.c
===================================================================
--- MacRuby/branches/testing/ext/openssl/ossl_bn.c	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/ext/openssl/ossl_bn.c	2008-06-05 08:33:02 UTC (rev 249)
@@ -1,5 +1,5 @@
 /*
- * $Id: ossl_bn.c 14377 2007-12-21 02:31:11Z akr $
+ * $Id: ossl_bn.c 16689 2008-05-29 17:41:56Z knu $
  * 'OpenSSL for Ruby' project
  * Copyright (C) 2001-2002  Technorama team <oss-ruby at technorama.net>
  * All rights reserved.
@@ -515,7 +515,7 @@
 	    bottom = (odd == Qtrue) ? 1 : 0;			\
 	    /* FALLTHROUGH */					\
 	case 2:							\
-	    top = FIX2INT(fill);				\
+	    top = NUM2INT(fill);				\
 	}							\
 	b = NUM2INT(bits);					\
 	if (!(result = BN_new())) {				\

Modified: MacRuby/branches/testing/ext/openssl/ossl_pkcs5.c
===================================================================
--- MacRuby/branches/testing/ext/openssl/ossl_pkcs5.c	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/ext/openssl/ossl_pkcs5.c	2008-06-05 08:33:02 UTC (rev 249)
@@ -27,7 +27,7 @@
 {
 #ifdef HAVE_PKCS5_PBKDF2_HMAC
     VALUE str;
-    const EVP_MD md;
+    const EVP_MD *md;
     int len = NUM2INT(keylen);
 
     StringValue(pass);

Modified: MacRuby/branches/testing/ext/openssl/ossl_pkey_dh.c
===================================================================
--- MacRuby/branches/testing/ext/openssl/ossl_pkey_dh.c	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/ext/openssl/ossl_pkey_dh.c	2008-06-05 08:33:02 UTC (rev 249)
@@ -1,5 +1,5 @@
 /*
- * $Id: ossl_pkey_dh.c 15610 2008-02-26 07:07:26Z technorama $
+ * $Id: ossl_pkey_dh.c 16689 2008-05-29 17:41:56Z knu $
  * 'OpenSSL for Ruby' project
  * Copyright (C) 2001-2002  Michal Rokos <m.rokos at sh.cvut.cz>
  * All rights reserved.
@@ -116,9 +116,9 @@
     VALUE size, gen, obj;
 	
     if (rb_scan_args(argc, argv, "11", &size, &gen) == 2) {
-	g = FIX2INT(gen);
+	g = NUM2INT(gen);
     }
-    dh = dh_generate(FIX2INT(size), g);
+    dh = dh_generate(NUM2INT(size), g);
     obj = dh_instance(klass, dh);
     if (obj == Qfalse) {
 	DH_free(dh);
@@ -158,7 +158,7 @@
     }
     else if (FIXNUM_P(arg)) {
 	if (!NIL_P(gen)) {
-	    g = FIX2INT(gen);
+	    g = NUM2INT(gen);
 	}
 	if (!(dh = dh_generate(FIX2INT(arg), g))) {
 	    ossl_raise(eDHError, NULL);

Modified: MacRuby/branches/testing/ext/openssl/ossl_pkey_dsa.c
===================================================================
--- MacRuby/branches/testing/ext/openssl/ossl_pkey_dsa.c	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/ext/openssl/ossl_pkey_dsa.c	2008-06-05 08:33:02 UTC (rev 249)
@@ -1,5 +1,5 @@
 /*
- * $Id: ossl_pkey_dsa.c 15610 2008-02-26 07:07:26Z technorama $
+ * $Id: ossl_pkey_dsa.c 16689 2008-05-29 17:41:56Z knu $
  * 'OpenSSL for Ruby' project
  * Copyright (C) 2001-2002  Michal Rokos <m.rokos at sh.cvut.cz>
  * All rights reserved.
@@ -110,7 +110,7 @@
 static VALUE
 ossl_dsa_s_generate(VALUE klass, VALUE size)
 {
-    DSA *dsa = dsa_generate(FIX2INT(size)); /* err handled by dsa_instance */
+    DSA *dsa = dsa_generate(NUM2INT(size)); /* err handled by dsa_instance */
     VALUE obj = dsa_instance(klass, dsa);
 
     if (obj == Qfalse) {

Modified: MacRuby/branches/testing/ext/openssl/ossl_rand.c
===================================================================
--- MacRuby/branches/testing/ext/openssl/ossl_rand.c	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/ext/openssl/ossl_rand.c	2008-06-05 08:33:02 UTC (rev 249)
@@ -1,5 +1,5 @@
 /*
- * $Id: ossl_rand.c 14696 2007-12-25 11:31:51Z technorama $
+ * $Id: ossl_rand.c 16692 2008-05-29 18:15:50Z knu $
  * 'OpenSSL for Ruby' project
  * Copyright (C) 2001-2002  Michal Rokos <m.rokos at sh.cvut.cz>
  * All rights reserved.
@@ -96,9 +96,10 @@
 ossl_rand_bytes(VALUE self, VALUE len)
 {
     VALUE str;
+    int n = NUM2INT(len);
 	
-    str = rb_str_new(0, FIX2INT(len));
-    if (!RAND_bytes(RSTRING_PTR(str), FIX2INT(len))) {
+    str = rb_str_new(0, n);
+    if (!RAND_bytes(RSTRING_PTR(str), n)) {
 	ossl_raise(eRandomError, NULL);
     }
 
@@ -114,9 +115,10 @@
 ossl_rand_pseudo_bytes(VALUE self, VALUE len)
 {
     VALUE str;
+    int n = NUM2INT(len);
 
-    str = rb_str_new(0, FIX2INT(len));
-    if (!RAND_pseudo_bytes(RSTRING_PTR(str), FIX2INT(len))) {
+    str = rb_str_new(0, n);
+    if (!RAND_pseudo_bytes(RSTRING_PTR(str), n)) {
 	ossl_raise(eRandomError, NULL);
     }
 
@@ -147,9 +149,11 @@
 static VALUE
 ossl_rand_egd_bytes(VALUE self, VALUE filename, VALUE len)
 {
+    long n = NUM2INT(len);
+
     SafeStringValue(filename);
 
-    if (!RAND_egd_bytes(RSTRING_PTR(filename), FIX2INT(len))) {
+    if (!RAND_egd_bytes(RSTRING_PTR(filename), n)) {
 	ossl_raise(eRandomError, NULL);
     }
     return Qtrue;

Modified: MacRuby/branches/testing/ext/openssl/ossl_x509store.c
===================================================================
--- MacRuby/branches/testing/ext/openssl/ossl_x509store.c	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/ext/openssl/ossl_x509store.c	2008-06-05 08:33:02 UTC (rev 249)
@@ -1,5 +1,5 @@
 /*
- * $Id: ossl_x509store.c 12153 2007-04-05 19:03:28Z technorama $
+ * $Id: ossl_x509store.c 16689 2008-05-29 17:41:56Z knu $
  * 'OpenSSL for Ruby' project
  * Copyright (C) 2001-2002  Michal Rokos <m.rokos at sh.cvut.cz>
  * All rights reserved.
@@ -458,7 +458,7 @@
     X509_STORE_CTX *ctx;
 
     GetX509StCtx(self, ctx);
-    X509_STORE_CTX_set_error(ctx, FIX2INT(err));
+    X509_STORE_CTX_set_error(ctx, NUM2INT(err));
 
     return err;
 }

Modified: MacRuby/branches/testing/ext/purelib.rb
===================================================================
--- MacRuby/branches/testing/ext/purelib.rb	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/ext/purelib.rb	2008-06-05 08:33:02 UTC (rev 249)
@@ -1,3 +1,10 @@
-if nul = $:.find_index {|path| /\A(?:\.\/)*-\z/ =~ path}
+nul = nil
+$:.each_with_index {|path, index|
+  if /\A(?:\.\/)*-\z/ =~ path
+    nul = index
+    break
+  end
+}
+if nul
   $:[nul..-1] = ["."]
 end

Modified: MacRuby/branches/testing/ext/stringio/stringio.c
===================================================================
--- MacRuby/branches/testing/ext/stringio/stringio.c	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/ext/stringio/stringio.c	2008-06-05 08:33:02 UTC (rev 249)
@@ -622,7 +622,7 @@
 	char c = RSTRING_PTR(ptr->string)[ptr->pos++];
 	rb_yield(CHR2FIX(c));
     }
-    return Qnil;
+    return self;
 }
 
 /*
@@ -768,6 +768,25 @@
     return c;
 }
 
+/*
+ * call-seq:
+ *   strio.each_char {|char| block }  -> strio
+ *
+ * See IO#each_char.
+ */
+static VALUE
+strio_each_char(VALUE self)
+{
+    VALUE c;
+
+    RETURN_ENUMERATOR(self, 0, 0);
+
+    while (!NIL_P(c = strio_getc(self))) {
+	rb_yield(c);
+    }
+    return self;
+}
+
 /* Boyer-Moore search: copied from regex.c */
 static void
 bm_init_skip(long *skip, const char *pat, long m)
@@ -1250,10 +1269,12 @@
     rb_define_method(StringIO, "path", strio_path, 0);
 
     rb_define_method(StringIO, "each", strio_each, -1);
-    rb_define_method(StringIO, "each_byte", strio_each_byte, 0);
-    rb_define_method(StringIO, "bytes", strio_each_byte, -1);
     rb_define_method(StringIO, "each_line", strio_each, -1);
     rb_define_method(StringIO, "lines", strio_each, -1);
+    rb_define_method(StringIO, "each_byte", strio_each_byte, 0);
+    rb_define_method(StringIO, "bytes", strio_each_byte, 0);
+    rb_define_method(StringIO, "each_char", strio_each_char, 0);
+    rb_define_method(StringIO, "chars", strio_each_char, 0);
     rb_define_method(StringIO, "getc", strio_getc, 0);
     rb_define_method(StringIO, "ungetc", strio_ungetc, 1);
     rb_define_method(StringIO, "readchar", strio_readchar, 0);

Modified: MacRuby/branches/testing/ext/strscan/strscan.c
===================================================================
--- MacRuby/branches/testing/ext/strscan/strscan.c	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/ext/strscan/strscan.c	2008-06-05 08:33:02 UTC (rev 249)
@@ -674,7 +674,11 @@
     if (EOS_P(p))
         return Qnil;
 
+#if WITH_OBJC
+    len = 1;
+#else
     len = rb_enc_mbclen(CURPTR(p), S_PEND(p), rb_enc_get(p->str));
+#endif
     if (p->curr + len > S_LEN(p)) {
         len = S_LEN(p) - p->curr;
     }

Modified: MacRuby/branches/testing/ext/zlib/extconf.rb
===================================================================
--- MacRuby/branches/testing/ext/zlib/extconf.rb	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/ext/zlib/extconf.rb	2008-06-05 08:33:02 UTC (rev 249)
@@ -1,7 +1,7 @@
 #
 # extconf.rb
 #
-# $Id: extconf.rb 11708 2007-02-12 23:01:19Z shyouhei $
+# $Id: extconf.rb 16677 2008-05-29 08:52:31Z nobu $
 #
 
 require 'mkmf'
@@ -10,7 +10,7 @@
 dir_config 'zlib'
 
 
-if %w'z libz zlib zdll'.find {|z| have_library(z, 'deflateReset')} and
+if %w'z libz zlib1 zlib zdll'.find {|z| have_library(z, 'deflateReset')} and
     have_header('zlib.h') then
 
   defines = []
@@ -22,7 +22,7 @@
       os_code = 'AMIGA'
     when /\Aos2[\-_]emx\z/ then
       os_code = 'OS2'
-    when 'mswin32', 'mingw32', 'bccwin32' then
+    when /mswin|mingw|bccwin/ then
       # NOTE: cygwin should be regarded as Unix.
       os_code = 'WIN32'
     else

Modified: MacRuby/branches/testing/file.c
===================================================================
--- MacRuby/branches/testing/file.c	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/file.c	2008-06-05 08:33:02 UTC (rev 249)
@@ -2392,7 +2392,10 @@
     return INT2FIX(omask);
 }
 
-#if defined DOSISH
+#ifdef __CYGWIN__
+#undef DOSISH
+#endif
+#if defined __CYGWIN__ || defined DOSISH
 #define DOSISH_UNC
 #define DOSISH_DRIVE_LETTER
 #define isdirsep(x) ((x) == '/' || (x) == '\\')
@@ -2552,6 +2555,7 @@
 static char *
 ntfs_tail(const char *path)
 {
+    while (*path == '.') path++;
     while (*path && *path != ':') {
 	if (istrailinggabage(*path)) {
 	    const char *last = path++;
@@ -2574,13 +2578,13 @@
 
 #define BUFCHECK(cond) do {\
     long bdiff = p - buf;\
-    while (cond) {\
-	buflen *= 2;\
+    if (cond) {\
+	do {buflen *= 2;} while (cond);\
+	rb_str_resize(result, buflen);\
+	buf = RSTRING_PTR(result);\
+	p = buf + bdiff;\
+	pend = buf + buflen;\
     }\
-    rb_str_resize(result, buflen);\
-    buf = RSTRING_PTR(result);\
-    p = buf + bdiff;\
-    pend = buf + buflen;\
 } while (0)
 
 #define BUFINIT() (\
@@ -2605,7 +2609,9 @@
     char *buf, *p, *pend, *root;
     long buflen, dirlen;
     int tainted;
+#if !WITH_OBJC
     rb_encoding *extenc = 0;
+#endif
 
     FilePathValue(fname);
     s = StringValuePtr(fname);
@@ -2735,8 +2741,11 @@
     }
     if (p > buf && p[-1] == '/')
 	--p;
-    else
+    else {
+	++buflen;
+	BUFCHECK(bdiff >= buflen);
 	*p = '/';
+    }
 
     p[1] = 0;
     root = skipprefix(buf);
@@ -2829,19 +2838,23 @@
 	p += s-b;
     }
     if (p == skiproot(buf) - 1) p++;
-    buflen = p - buf;
 
 #if USE_NTFS
     *p = '\0';
-    if (!strpbrk(b = buf, "*?")) {
+    if (1 &&
+#ifdef __CYGWIN__
+	!(buf[0] == '/' && !buf[1]) &&
+#endif
+	!strpbrk(b = buf, "*?")) {
 	size_t len;
 	WIN32_FIND_DATA wfd;
 #ifdef __CYGWIN__
-	int lnk_added = 0;
+	int lnk_added = 0, is_symlink = 0;
 	struct stat st;
 	char w32buf[MAXPATHLEN], sep = 0;
 	p = 0;
 	if (lstat(buf, &st) == 0 && S_ISLNK(st.st_mode)) {
+	    is_symlink = 1;
 	    p = strrdirsep(buf);
 	    if (!p) p = skipprefix(buf);
 	    if (p) {
@@ -2854,8 +2867,7 @@
 	}
 	if (p) *p = sep;
 	else p = buf;
-	if (b == w32buf) {
-	    strlcat(w32buf, p, sizeof(w32buf));
+	if (is_symlink && b == w32buf) {
 	    len = strlen(p);
 	    if (len > 4 && STRCASECMP(p + len - 4, ".lnk") != 0) {
 		lnk_added = 1;
@@ -2871,19 +2883,20 @@
 #ifdef __CYGWIN__
 	    if (lnk_added && len > 4 &&
 		STRCASECMP(wfd.cFileName + len - 4, ".lnk") == 0) {
-		len -= 4;
+		wfd.cFileName[len -= 4] = '\0';
 	    }
 #endif
 	    if (!p) p = buf;
-	    buflen = ++p - buf + len;
-	    rb_str_resize(result, buflen);
+	    else ++p;
+	    BUFCHECK(bdiff + len >= buflen);
 	    memcpy(p, wfd.cFileName, len + 1);
+	    p += len;
 	}
     }
 #endif
 
     if (tainted) OBJ_TAINT(result);
-    rb_str_set_len(result, buflen);
+    rb_str_set_len(result, p - buf);
 #if !WITH_OBJC
     rb_enc_check(fname, result);
 #endif
@@ -3117,7 +3130,7 @@
     if (!p)
 	p = name;
     else
-	p++;
+	name = ++p;
 
     e = 0;
     while (*p) {
@@ -3147,7 +3160,7 @@
 	    break;
 	p = CharNext(p);
     }
-    if (!e || e+1 == p)	/* no dot, or the only dot is first or end? */
+    if (!e || e == name || e+1 == p)	/* no dot, or the only dot is first or end? */
 	return rb_str_new(0, 0);
     extname = rb_str_new(e, p - e);	/* keep the dot, too! */
 #if !WITH_OBJC
@@ -3196,6 +3209,7 @@
 
 static VALUE rb_file_join(VALUE ary, VALUE sep);
 
+#if !WITH_OBJC
 static VALUE
 file_inspect_join(VALUE ary, VALUE argp, int recur)
 {
@@ -3203,6 +3217,7 @@
     if (recur) return rb_usascii_str_new2("[...]");
     return rb_file_join(arg[0], arg[1]);
 }
+#endif
 
 static VALUE
 rb_file_join(VALUE ary, VALUE sep)

Modified: MacRuby/branches/testing/gc.c
===================================================================
--- MacRuby/branches/testing/gc.c	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/gc.c	2008-06-05 08:33:02 UTC (rev 249)
@@ -38,6 +38,7 @@
 #endif
 
 #if WITH_OBJC
+# include <mach/mach.h>
 # if HAVE_AUTO_ZONE_H
 #  include <auto_zone.h>
 # else
@@ -904,7 +905,7 @@
     if (!SPECIAL_CONST_P(newval)) {
 	//printf("rb_objc_wb %p %p\n", dst, newval);
 	if (!auto_zone_set_write_barrier(__auto_zone, dst, newval))
-	    rb_bug("destination %p isn't in the auto zone");
+	    rb_bug("destination %p isn't in the auto zone", dst);
     }
     *(void **)dst = newval;
 }
@@ -929,17 +930,17 @@
 }
 
 void
-rb_objc_retain(void *addr)
+rb_objc_retain(const void *addr)
 {
     if (addr != NULL && !SPECIAL_CONST_P(addr))
-	auto_zone_retain(__auto_zone, addr);
+	auto_zone_retain(__auto_zone, (void *)addr);
 }
 
 void
-rb_objc_release(void *addr)
+rb_objc_release(const void *addr)
 {
     if (addr != NULL && !SPECIAL_CONST_P(addr))
-	auto_zone_release(__auto_zone, addr);
+	auto_zone_release(__auto_zone, (void *)addr);
 }
 
 void
@@ -1056,7 +1057,7 @@
     NEWOBJ(data, struct RData);
     if (klass) Check_Type(klass, T_CLASS);
     OBJSETUP(data, klass, T_DATA);
-    data->data = datap;
+    GC_WB(&data->data, datap);
     data->dfree = dfree;
     data->dmark = dmark;
 
@@ -2281,8 +2282,7 @@
 	    switch (BUILTIN_TYPE(r->address)) {
 		case T_NONE: 
 		case T_ICLASS: 
-		case T_NODE: 
-		case T_VALUES: 
+		case T_NODE:
 		    continue;
 		case T_CLASS:
 		    if (FL_TEST(r->address, FL_SINGLETON))
@@ -2419,7 +2419,7 @@
 	CFDictionaryRemoveValue(__os_finalizers, (const void *)obj);
     
     if (rb_objc_is_non_native(obj)) {
-	rb_objc_flag_set(obj, FL_FINALIZE, false);
+	rb_objc_flag_set((void *)obj, FL_FINALIZE, false);
     }
     else {
 	FL_UNSET(obj, FL_FINALIZE);
@@ -2473,7 +2473,7 @@
     rb_ary_push(table, block);
     
     if (rb_objc_is_non_native(obj)) {
-	rb_objc_flag_set(obj, FL_FINALIZE, true);
+	rb_objc_flag_set((void *)obj, FL_FINALIZE, true);
     }
     else {
 	FL_SET(obj, FL_FINALIZE);
@@ -2504,8 +2504,8 @@
     else {
 	st_add_direct(finalizer_table, obj, rb_ary_new3(1, block));
     }
-    return block;
 #endif
+    return block;
 }
 
 void
@@ -2518,7 +2518,7 @@
 	return;
 
     if (rb_objc_is_non_native(obj)) {
-	if (!rb_objc_flag_check(obj, FL_FINALIZE))
+	if (!rb_objc_flag_check((void *)obj, FL_FINALIZE))
 	    return;
     }
     else {
@@ -2784,8 +2784,7 @@
 	if ((type == AUTO_OBJECT_SCANNED || type == AUTO_OBJECT_UNSCANNED)
 	    && !rb_objc_is_placeholder(p0)
 	    && (rb_objc_is_non_native((VALUE)p0)
-		|| (BUILTIN_TYPE(p0) < T_VALUES 
-		    && BUILTIN_TYPE(p0) != T_ICLASS)))
+		|| (BUILTIN_TYPE(p0) < T_FIXNUM && BUILTIN_TYPE(p0) != T_ICLASS)))
 	    return (VALUE)p0;
     }
     rb_raise(rb_eRangeError, "%p is not id value", p0);

Modified: MacRuby/branches/testing/hash.c
===================================================================
--- MacRuby/branches/testing/hash.c	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/hash.c	2008-06-05 08:33:02 UTC (rev 249)
@@ -2,7 +2,7 @@
 
   hash.c -
 
-  $Author: matz $
+  $Author: knu $
   created at: Mon Nov 22 18:51:18 JST 1993
 
   Copyright (C) 1993-2007 Yukihiro Matsumoto
@@ -371,7 +371,7 @@
 rb_hash_modify_check(VALUE hash)
 {
     long mask;
-    mask = rb_objc_flag_get_mask(hash);
+    mask = rb_objc_flag_get_mask((const void *)hash);
     if (mask == 0) {
 	bool _CFDictionaryIsMutable(void *);
 	if (!_CFDictionaryIsMutable((void *)hash))
@@ -508,7 +508,7 @@
 	    hash = hash_alloc(klass);
 	    count = CFDictionaryGetCount((CFDictionaryRef)tmp);
 	    if (count == 0)
-		return;
+		return hash;
 
 	    keys = (const void **)alloca(sizeof(void *) * count);
 	    values = (const void **)alloca(sizeof(void *) * count);
@@ -836,8 +836,8 @@
 #else
     RHASH(hash)->ifnone = ifnone;
     FL_UNSET(hash, HASH_PROC_DEFAULT);
+#endif
     return ifnone;
-#endif
 }
 
 /*
@@ -975,6 +975,7 @@
     return Qnil;
 }
 
+#if !WITH_OBJC
 struct shift_var {
     VALUE key;
     VALUE val;
@@ -998,6 +999,7 @@
     var->val = value;
     return ST_STOP;
 }
+#endif
 
 /*
  *  call-seq:
@@ -1196,11 +1198,13 @@
     return result;
 }
 
+#if !WITH_OBJC
 static int
 clear_i(VALUE key, VALUE value, VALUE dummy)
 {
     return ST_DELETE;
 }
+#endif
 
 /*
  *  call-seq:
@@ -1652,6 +1656,7 @@
     return Qfalse;
 }
 
+#if !WITH_OBJC
 static int
 rb_hash_search_value(VALUE key, VALUE value, VALUE *data)
 {
@@ -1662,6 +1667,7 @@
     }
     return ST_CONTINUE;
 }
+#endif
 
 /*
  *  call-seq:
@@ -1692,6 +1698,7 @@
 #endif
 }
 
+#if !WITH_OBJC
 struct equal_data {
     VALUE result;
     st_table *tbl;
@@ -1727,12 +1734,11 @@
 
     return data->result;
 }
+#endif
 
 static VALUE
 hash_equal(VALUE hash1, VALUE hash2, int eql)
 {
-    struct equal_data data;
-
     if (hash1 == hash2) return Qtrue;
     if (TYPE(hash2) != T_HASH) {
 	if (!rb_respond_to(hash2, rb_intern("to_hash"))) {
@@ -2079,8 +2085,8 @@
 #else
     RHASH(hash)->ntbl->type = &identhash;
     rb_hash_rehash(hash);
+#endif
     return hash;
-#endif
 }
 
 /*
@@ -2436,8 +2442,7 @@
     long i;
 
     RETURN_ENUMERATOR(ehash, 0, 0);
-    rb_secure(4);
-    keys = env_keys();
+    keys = env_keys();	/* rb_secure(4); */
     for (i=0; i<RARRAY_LEN(keys); i++) {
 	rb_yield(RARRAY_AT(keys, i));
     }
@@ -2467,12 +2472,11 @@
 static VALUE
 env_each_value(VALUE ehash)
 {
-    VALUE values = env_values();
+    VALUE values;
     long i;
 
     RETURN_ENUMERATOR(ehash, 0, 0);
-    rb_secure(4);
-    values = env_values();
+    values = env_values();	/* rb_secure(4); */
     for (i=0; i<RARRAY_LEN(values); i++) {
 	rb_yield(RARRAY_AT(values, i));
     }
@@ -2515,8 +2519,7 @@
     int del = 0;
 
     RETURN_ENUMERATOR(ehash, 0, 0);
-    rb_secure(4);
-    keys = env_keys();
+    keys = env_keys();	/* rb_secure(4); */
     for (i=0; i<RARRAY_LEN(keys); i++) {
 	VALUE val = rb_f_getenv(Qnil, RARRAY_AT(keys, i));
 	if (!NIL_P(val)) {
@@ -2585,8 +2588,7 @@
     volatile VALUE keys;
     long i;
 
-    rb_secure(4);
-    keys = env_keys();
+    keys = env_keys();	/* rb_secure(4); */
     for (i=0; i<RARRAY_LEN(keys); i++) {
 	VALUE val = rb_f_getenv(Qnil, RARRAY_AT(keys, i));
 	if (!NIL_P(val)) {
@@ -2868,8 +2870,7 @@
     volatile VALUE keys;
     long i;
 
-    rb_secure(4);
-    keys = env_keys();
+    keys = env_keys();	/* rb_secure(4); */
     if (env == hash) return env;
     hash = to_hash(hash);
     rb_hash_foreach(hash, env_replace_i, keys);

Modified: MacRuby/branches/testing/id.c
===================================================================
--- MacRuby/branches/testing/id.c	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/id.c	2008-06-05 08:33:02 UTC (rev 249)
@@ -2,7 +2,7 @@
 
   id.c - 
 
-  $Author: akr $
+  $Author: ko1 $
   created at: Thu Jul 12 04:37:51 2007
 
   Copyright (C) 2004-2007 Koichi Sasada
@@ -63,4 +63,7 @@
 
     idSend = rb_intern("send");
     id__send__ = rb_intern("__send__");
+
+    idRespond_to = rb_intern("respond_to?");
+    idInitialize = rb_intern("initialize");
 }

Modified: MacRuby/branches/testing/id.h
===================================================================
--- MacRuby/branches/testing/id.h	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/id.h	2008-06-05 08:33:02 UTC (rev 249)
@@ -50,5 +50,6 @@
 extern ID idAnswer;
 extern ID idSend;
 extern ID id__send__;
-
+extern ID idRespond_to;
+extern ID idInitialize;
 #endif /* RUBY_ID_H */

Modified: MacRuby/branches/testing/include/ruby/defines.h
===================================================================
--- MacRuby/branches/testing/include/ruby/defines.h	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/include/ruby/defines.h	2008-06-05 08:33:02 UTC (rev 249)
@@ -294,6 +294,7 @@
 # include <CoreFoundation/CoreFoundation.h>
 # define ASSERT_NO_OBJC() (assert(1 == 0))
 void rb_objc_wb(void *dst, void *newval);
+void rb_objc_wb_range(void *dest, size_t len);
 void rb_objc_root(void *addr);
 # define GC_WB(dst, newval) (rb_objc_wb((void *)dst, (void *)newval))
 # define GC_ROOT(dst) (rb_objc_root((void *)dst))

Modified: MacRuby/branches/testing/include/ruby/encoding.h
===================================================================
--- MacRuby/branches/testing/include/ruby/encoding.h	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/include/ruby/encoding.h	2008-06-05 08:33:02 UTC (rev 249)
@@ -20,6 +20,8 @@
 
 #if WITH_OBJC
 
+#include <wctype.h>
+
 typedef CFStringEncoding rb_encoding;
 
 #else
@@ -40,14 +42,14 @@
     if (encoding_set_enc_index < ENCODING_INLINE_MAX) \
         ENCODING_SET_INLINED(rb_encoding_set_obj, encoding_set_enc_index); \
     else \
-        rb_enc_internal_set_index(rb_encoding_set_obj, encoding_set_enc_index); \
+        rb_enc_set_index(rb_encoding_set_obj, encoding_set_enc_index); \
 } while (0)
 
 #define ENCODING_GET_INLINED(obj) ((RBASIC(obj)->flags & ENCODING_MASK)>>ENCODING_SHIFT)
 #define ENCODING_GET(obj) \
     (ENCODING_GET_INLINED(obj) != ENCODING_INLINE_MAX ? \
      ENCODING_GET_INLINED(obj) : \
-     rb_enc_internal_get_index(obj))
+     rb_enc_get_index(obj))
 
 #if WITH_OBJC
 # define ENCODING_IS_ASCII8BIT(obj) (1)
@@ -86,20 +88,18 @@
 
 int rb_enc_replicate(const char *, rb_encoding *);
 int rb_define_dummy_encoding(const char *);
-int rb_enc_dummy_p(rb_encoding *);
 #define rb_enc_to_index(enc) ((enc) ? ((enc)->ruby_encoding_index) : 0)
 int rb_enc_get_index(VALUE obj);
+void rb_enc_set_index(VALUE obj, int encindex);
 int rb_enc_find_index(const char *name);
 int rb_to_encoding_index(VALUE);
 rb_encoding* rb_to_encoding(VALUE);
 rb_encoding* rb_enc_get(VALUE);
 rb_encoding* rb_enc_compatible(VALUE,VALUE);
 rb_encoding* rb_enc_check(VALUE,VALUE);
-void rb_enc_associate_index(VALUE, int);
-void rb_enc_associate(VALUE, rb_encoding*);
+VALUE rb_enc_associate_index(VALUE, int);
+VALUE rb_enc_associate(VALUE, rb_encoding*);
 void rb_enc_copy(VALUE dst, VALUE src);
-int rb_enc_internal_get_index(VALUE obj);
-void rb_enc_internal_set_index(VALUE obj, int encindex);
 
 VALUE rb_enc_str_new(const char*, long, rb_encoding*);
 VALUE rb_enc_reg_new(const char*, long, rb_encoding*, int);
@@ -192,7 +192,7 @@
 #define rb_enc_isdigit(c,enc) ONIGENC_IS_CODE_DIGIT(enc,c)
 #endif
 
-#define rb_enc_asciicompat(enc) (!rb_enc_dummy_p(enc) && rb_enc_mbminlen(enc)==1)
+#define rb_enc_asciicompat(enc) (rb_enc_mbminlen(enc)==1 && !rb_enc_dummy_p(enc))
 
 int rb_enc_casefold(char *to, const char *p, const char *e, rb_encoding *enc);
 int rb_enc_toupper(int c, rb_encoding *enc);
@@ -211,9 +211,33 @@
 rb_encoding *rb_locale_encoding(void);
 rb_encoding *rb_default_external_encoding(void);
 int rb_usascii_encindex(void);
+int rb_ascii8bit_encindex(void);
 VALUE rb_enc_default_external(void);
 void rb_enc_set_default_external(VALUE encoding);
 VALUE rb_locale_charmap(VALUE klass);
 long rb_memsearch(const void*,long,const void*,long,rb_encoding*);
 
+RUBY_EXTERN VALUE rb_cEncoding;
+
+#define ENC_UNINITIALIZED (&rb_cEncoding)
+#define enc_initialized_p(enc) ((enc)->auxiliary_data != &rb_cEncoding)
+#define ENC_FROM_ENCODING(enc) ((VALUE)(enc)->auxiliary_data)
+
+#define ENC_DUMMY_FLAG FL_USER2
+#define ENC_DUMMY_P(enc) (RBASIC(enc)->flags & ENC_DUMMY_FLAG)
+#define ENC_SET_DUMMY(enc) (RBASIC(enc)->flags |= ENC_DUMMY_FLAG)
+
+#if WITH_OBJC
+# define rb_enc_dummy_p(x) (Qfalse)
+#else
+static inline int
+rb_enc_dummy_p(rb_encoding *enc)
+{
+    if (!enc_initialized_p(enc)) return Qfalse;
+    return ENC_DUMMY_P(ENC_FROM_ENCODING(enc));
+}
+#endif
+
+VALUE rb_str_transcode(VALUE str, VALUE to);
+
 #endif /* RUBY_ENCODING_H */

Modified: MacRuby/branches/testing/include/ruby/intern.h
===================================================================
--- MacRuby/branches/testing/include/ruby/intern.h	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/include/ruby/intern.h	2008-06-05 08:33:02 UTC (rev 249)
@@ -2,7 +2,7 @@
 
   intern.h -
 
-  $Author: usa $
+  $Author: nobu $
   created at: Thu Jun 10 14:22:17 JST 1993
 
   Copyright (C) 1993-2007 Yukihiro Matsumoto
@@ -79,8 +79,6 @@
 VALUE rb_get_values_at(VALUE, long, int, VALUE*, VALUE(*)(VALUE,long));
 #if WITH_OBJC
 VALUE rb_ary_elt(VALUE, long);
-void rb_ary_set_named_args(VALUE, bool);
-bool rb_ary_is_named_args(VALUE);
 bool rb_objc_ary_is_pure(VALUE);
 #endif
 /* bignum.c */
@@ -346,6 +344,9 @@
 void rb_objc_gc_unregister_thread(void);
 void rb_objc_set_associative_ref(void *, void *, void *);
 void *rb_objc_get_associative_ref(void *, void *);
+void rb_objc_retain(const void *);
+void rb_objc_release(const void *);
+void rb_gc_malloc_increase(size_t);
 # define rb_gc_mark_locations(x,y)
 # define rb_mark_tbl(x)
 # define rb_mark_set(x)
@@ -617,7 +618,7 @@
 VALUE rb_struct_s_members(VALUE);
 VALUE rb_struct_members(VALUE);
 VALUE rb_struct_alloc_noinit(VALUE);
-VALUE rb_struct_define_without_accessor(char *, VALUE, rb_alloc_func_t, ...);
+VALUE rb_struct_define_without_accessor(const char *, VALUE, rb_alloc_func_t, ...);
 /* thread.c */
 typedef void rb_unblock_function_t(void *);
 typedef VALUE rb_blocking_function_t(void *);
@@ -693,10 +694,14 @@
 VALUE rb_mod_objc_ib_outlet(int, VALUE *, VALUE);
 VALUE rb_require_framework(int, VALUE *, VALUE);
 VALUE rb_objc_resolve_const_value(VALUE, VALUE, ID);
-ID rb_objc_missing_sel(ID mid, int arity);
-void rb_objc_install_ivar_cluster(Class);
-void *rb_objc_get_ivar_cluster(void *);
-void rb_objc_set_ivar_cluster(void *, void *);
+ID rb_objc_missing_sel(ID, int);
+long rb_objc_flag_get_mask(const void *);
+void rb_objc_flag_set(const void *, int, bool);
+bool rb_objc_flag_check(const void *, int);
+long rb_objc_remove_flags(const void *obj);
+void rb_objc_sync_ruby_methods(VALUE, VALUE);
+void rb_objc_methods(VALUE, Class);
+bool rb_objc_is_immutable(VALUE);
 #endif
 /* version.c */
 void ruby_show_version(void);

Copied: MacRuby/branches/testing/include/ruby/mvm.h (from rev 248, MacRuby/trunk/include/ruby/mvm.h)
===================================================================
--- MacRuby/branches/testing/include/ruby/mvm.h	                        (rev 0)
+++ MacRuby/branches/testing/include/ruby/mvm.h	2008-06-05 08:33:02 UTC (rev 249)
@@ -0,0 +1,18 @@
+/**********************************************************************
+
+  ruby/mvm.h -
+
+  $Author: nobu $
+  created at: Sat May 31 15:17:36 2008
+
+  Copyright (C) 2008 Yukihiro Matsumoto
+
+**********************************************************************/
+
+#ifndef RUBY_MVM_H
+#define RUBY_MVM_H 1
+
+typedef struct rb_vm_struct rb_vm_t;
+typedef struct rb_thread_struct rb_thread_t;
+
+#endif /* RUBY_MVM_H */

Modified: MacRuby/branches/testing/include/ruby/node.h
===================================================================
--- MacRuby/branches/testing/include/ruby/node.h	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/include/ruby/node.h	2008-06-05 08:33:02 UTC (rev 249)
@@ -425,9 +425,15 @@
 #define NEW_DXSTR(s) NEW_NODE(NODE_DXSTR,s,0,0)
 #define NEW_DSYM(s) NEW_NODE(NODE_DSYM,s,0,0)
 #define NEW_EVSTR(n) NEW_NODE(NODE_EVSTR,0,(n),0)
-#define NEW_CALL(r,m,a) NEW_NODE(NODE_CALL,r,m,a)
-#define NEW_FCALL(m,a) NEW_NODE(NODE_FCALL,0,m,a)
-#define NEW_VCALL(m) NEW_NODE(NODE_VCALL,0,m,0)
+#if WITH_OBJC
+# define NEW_CALL(r,m,a) process_named_args(NEW_NODE(NODE_CALL,r,m,a))
+# define NEW_FCALL(m,a) process_named_args(NEW_NODE(NODE_FCALL,0,m,a))
+# define NEW_VCALL(m) process_named_args(NEW_NODE(NODE_VCALL,0,m,0))
+#else
+# define NEW_CALL(r,m,a) NEW_NODE(NODE_CALL,r,m,a)
+# define NEW_FCALL(m,a) NEW_NODE(NODE_FCALL,0,m,a)
+# define NEW_VCALL(m) NEW_NODE(NODE_VCALL,0,m,0)
+#endif
 #define NEW_SUPER(a) NEW_NODE(NODE_SUPER,0,0,a)
 #define NEW_ZSUPER() NEW_NODE(NODE_ZSUPER,0,0,0)
 #define NEW_ARGS(m,o) NEW_NODE(NODE_ARGS,o,m,0)

Modified: MacRuby/branches/testing/include/ruby/ruby.h
===================================================================
--- MacRuby/branches/testing/include/ruby/ruby.h	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/include/ruby/ruby.h	2008-06-05 08:33:02 UTC (rev 249)
@@ -1,18 +1,18 @@
 /**********************************************************************
 
-  ruby.h -
+  ruby/ruby.h -
 
-  $Author: akr $
+  $Author: nobu $
   created at: Thu Jun 10 14:26:32 JST 1993
 
-  Copyright (C) 1993-2007 Yukihiro Matsumoto
+  Copyright (C) 1993-2008 Yukihiro Matsumoto
   Copyright (C) 2000  Network Applied Communication Laboratory, Inc.
   Copyright (C) 2000  Information-technology Promotion Agency, Japan
 
 **********************************************************************/
 
-#ifndef RUBY_H
-#define RUBY_H 1
+#ifndef RUBY_RUBY_H
+#define RUBY_RUBY_H 1
 
 #if defined(__cplusplus)
 extern "C" {
@@ -21,6 +21,7 @@
 #endif
 #endif
 
+#ifndef RUBY_LIB
 #if RUBY_INCLUDED_AS_FRAMEWORK
 #include <MacRuby/ruby/config.h>
 #else
@@ -29,6 +30,7 @@
 #ifdef RUBY_EXTCONF_H
 #include RUBY_EXTCONF_H
 #endif
+#endif
 
 #define NORETURN_STYLE_NEW 1
 #ifndef NORETURN
@@ -93,12 +95,24 @@
 typedef unsigned long ID;
 # define SIGNED_VALUE long
 # define SIZEOF_VALUE SIZEOF_LONG
+# define PRIdVALUE "ld"
+# define PRIiVALUE "li"
+# define PRIoVALUE "lo"
+# define PRIuVALUE "lu"
+# define PRIxVALUE "lx"
+# define PRIXVALUE "lX"
 #elif SIZEOF_LONG_LONG == SIZEOF_VOIDP
 typedef unsigned LONG_LONG VALUE;
 typedef unsigned LONG_LONG ID;
 # define SIGNED_VALUE LONG_LONG
 # define LONG_LONG_VALUE 1
 # define SIZEOF_VALUE SIZEOF_LONG_LONG
+# define PRIdVALUE "lld"
+# define PRIiVALUE "lli"
+# define PRIoVALUE "llo"
+# define PRIuVALUE "llu"
+# define PRIxVALUE "llx"
+# define PRIXVALUE "llX"
 #else
 # error ---->> ruby requires sizeof(void*) == sizeof(long) to be compiled. <<----
 #endif
@@ -270,7 +284,6 @@
     RUBY_T_SYMBOL = 0x14,
     RUBY_T_FIXNUM = 0x15,
 
-    RUBY_T_VALUES = 0x1a,
     RUBY_T_UNDEF  = 0x1b,
     RUBY_T_NODE   = 0x1c,
     RUBY_T_ICLASS = 0x1d,
@@ -300,7 +313,6 @@
 #define T_SYMBOL RUBY_T_SYMBOL
 #define T_RATIONAL RUBY_T_RATIONAL
 #define T_COMPLEX RUBY_T_COMPLEX
-#define T_VALUES RUBY_T_VALUES
 #define T_UNDEF  RUBY_T_UNDEF
 #define T_NODE   RUBY_T_NODE
 #define T_MASK   RUBY_T_MASK
@@ -460,13 +472,6 @@
      RCLASS_IV_INDEX_TBL(rb_obj_class(o)) : \
      ROBJECT(o)->as.heap.iv_index_tbl)
 
-struct RValues {
-    struct RBasic basic;
-    VALUE v1;
-    VALUE v2;
-    VALUE v3;
-};
-
 typedef struct {
     VALUE super;
     struct st_table *iv_tbl;
@@ -852,8 +857,8 @@
         rb_intern(str))
 #endif
 
-char *rb_class2name(VALUE);
-char *rb_obj_classname(VALUE);
+const char *rb_class2name(VALUE);
+const char *rb_obj_classname(VALUE);
 
 void rb_p(VALUE);
 
@@ -896,7 +901,7 @@
 VALUE rb_each(VALUE);
 VALUE rb_yield(VALUE);
 VALUE rb_yield_values(int n, ...);
-VALUE rb_yield_values2(int n, VALUE *argv);
+VALUE rb_yield_values2(int n, const VALUE *argv);
 VALUE rb_yield_splat(VALUE);
 int rb_block_given_p(void);
 void rb_need_block(void);
@@ -1198,4 +1203,4 @@
 #endif
 }  /* extern "C" { */
 #endif
-#endif /* RUBY_H */
+#endif /* RUBY_RUBY_H */

Modified: MacRuby/branches/testing/include/ruby/win32.h
===================================================================
--- MacRuby/branches/testing/include/ruby/win32.h	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/include/ruby/win32.h	2008-06-05 08:33:02 UTC (rev 249)
@@ -546,6 +546,7 @@
 size_t rb_w32_write(int, const void *, size_t);
 int  rb_w32_utime(const char *, const struct utimbuf *);
 int  WINAPI rb_w32_Sleep(unsigned long msec);
+int  rb_w32_wait_events_blocking(HANDLE *events, int num, DWORD timeout);
 
 /*
 == ***CAUTION***

Modified: MacRuby/branches/testing/include/ruby.h
===================================================================
--- MacRuby/branches/testing/include/ruby.h	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/include/ruby.h	2008-06-05 08:33:02 UTC (rev 249)
@@ -1 +1,21 @@
+/**********************************************************************
+
+  ruby/mvm.h -
+
+  $Author$
+  created at: Sun 10 12:06:15 Jun JST 2007
+
+  Copyright (C) 2007-2008 Yukihiro Matsumoto
+
+**********************************************************************/
+
+#ifndef RUBY_H
+#define RUBY_H 1
+
 #include <ruby/ruby.h>
+#if RUBY_VM
+#include <ruby/mvm.h>
+#endif
+
+extern void ruby_set_debug_option(const char *);
+#endif /* RUBY_H */

Modified: MacRuby/branches/testing/insns.def
===================================================================
--- MacRuby/branches/testing/insns.def	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/insns.def	2008-06-05 08:33:02 UTC (rev 249)
@@ -183,7 +183,8 @@
 ()
 (VALUE val)
 {
-    val = rb_cvar_get(vm_get_cvar_base(th, GET_ISEQ()), id);
+    NODE * const cref = vm_get_cref(GET_ISEQ(), GET_LFP(), GET_DFP());
+    val = rb_cvar_get(vm_get_cvar_base(cref), id);
 }
 
 /**
@@ -197,7 +198,8 @@
 (VALUE val)
 ()
 {
-    rb_cvar_set(vm_get_cvar_base(th, GET_ISEQ()), id, val);
+    NODE * const cref = vm_get_cref(GET_ISEQ(), GET_LFP(), GET_DFP());
+    rb_cvar_set(vm_get_cvar_base(cref), id, val);
 }
 
 /**
@@ -317,7 +319,7 @@
 ()
 (VALUE val)
 {
-    val = vm_get_cbase(th);
+    val = vm_get_cbase(GET_ISEQ(), GET_LFP(), GET_DFP());
 }
 
 /**
@@ -362,11 +364,10 @@
 (VALUE val) // inc += 1 - num;
 {
     int i;
-    VALUE v;
 
     val = rb_str_new(0, 0);
     for (i = num - 1; i >= 0; i--) {
-	v = TOPN(i);
+	const VALUE v = TOPN(i);
 	rb_str_append(val, v);
     }
     POPN(num);
@@ -400,7 +401,7 @@
 {
     VALUE rb_reg_new_ary(VALUE ary, int options);
     int i;
-    VALUE ary = rb_ary_new2(cnt);
+    const VALUE ary = rb_ary_new2(cnt);
     RBASIC(ary)->klass = 0;
     for (i = 0; i < cnt; i++) {
         rb_ary_store(ary, cnt-i-1, TOPN(i));
@@ -426,22 +427,6 @@
 
 /**
   @c put
-  @e put new array, that contains named args (MacRuby only).
-  @j n/a yet
- */
-DEFINE_INSN
-newarray_named_args
-(rb_num_t num)
-(...)
-(VALUE val) // inc += 1 - num;
-{
-    val = rb_ary_new4((long)num, STACK_ADDR_FROM_TOP(num));
-    rb_ary_set_named_args(val, true);
-    POPN(num);
-}
-
-/**
-  @c put
   @e dup array
   @j \x94z\x97\xF1 ary \x82\xF0 dup \x82\xB5\x82ăX\x83^\x83b\x83N\x82Ƀv\x83b\x83V\x83\x85\x82\xB7\x82\xE9\x81B
  */
@@ -454,16 +439,6 @@
     val = rb_ary_dup(ary);
 }
 
-DEFINE_INSN
-duparray_named_args
-(VALUE ary)
-()
-(VALUE val)
-{
-    val = rb_ary_dup(ary);
-    rb_ary_set_named_args(val, true);
-}
-
 /**
   @c put
   @e expand array to num objects.
@@ -496,7 +471,7 @@
 (VALUE ary1, VALUE ary2st)
 (VALUE ary)
 {
-    VALUE ary2 = ary2st;
+    const VALUE ary2 = ary2st;
     VALUE tmp1 = rb_check_convert_type(ary1, T_ARRAY, "Array", "to_a");
     VALUE tmp2 = rb_check_convert_type(ary2, T_ARRAY, "Array", "to_a");
 
@@ -585,12 +560,11 @@
 (VALUE val) // inc += 1 - num;
 {
     int i;
-    VALUE k, v;
     val = rb_hash_new();
 
     for (i = num; i > 0; i -= 2) {
-	v = TOPN(i - 2);
-	k = TOPN(i - 1);
+	const VALUE v = TOPN(i - 2);
+	const VALUE k = TOPN(i - 1);
 	rb_hash_aset(val, k, v);
     }
     POPN(num);
@@ -749,8 +723,8 @@
 (VALUE obj)
 ()
 {
-    vm_define_method(th, obj, id, body, is_singleton,
-		     get_cref(GET_ISEQ(), GET_LFP()));
+    NODE *cref = vm_get_cref(GET_ISEQ(), GET_LFP(), GET_DFP());
+    vm_define_method(th, obj, id, body, is_singleton, cref);
 }
 
 /**
@@ -764,13 +738,11 @@
 (VALUE sym1, VALUE sym2)
 ()
 {
-    VALUE klass;
-
     if (v_p == Qtrue) {
 	rb_alias_variable(SYM2ID(sym1), SYM2ID(sym2));
     }
     else {
-	klass = get_cref(GET_ISEQ(), GET_LFP())->nd_clss;
+	const VALUE klass = vm_get_cbase(GET_ISEQ(), GET_LFP(), GET_DFP());
 	rb_alias(klass, SYM2ID(sym1), SYM2ID(sym2));
     }
 }
@@ -786,7 +758,7 @@
 (VALUE sym)
 ()
 {
-    VALUE klass = get_cref(GET_ISEQ(), GET_LFP())->nd_clss;
+    const VALUE klass = vm_get_cbase(GET_ISEQ(), GET_LFP(), GET_DFP());
     rb_undef(klass, SYM2ID(sym));
     INC_VM_STATE_VERSION();
 }
@@ -803,7 +775,7 @@
 (VALUE val)
 {
     VALUE klass;
-    char *expr_type = 0;
+    const char *expr_type = 0;
     val = Qnil;
 
     switch (type) {
@@ -813,7 +785,7 @@
 	}
 	break;
       case DEFINED_IVAR2:
-	klass = get_cref(GET_ISEQ(), GET_LFP())->nd_clss;
+	klass = vm_get_cbase(GET_ISEQ(), GET_LFP(), GET_DFP());
 	break;
       case DEFINED_GVAR:
 	if (rb_gvar_defined((struct global_entry *)(obj & ~1))) {
@@ -821,7 +793,7 @@
 	}
 	break;
       case DEFINED_CVAR:
-	klass = get_cref(GET_ISEQ(), GET_LFP())->nd_clss;
+	klass = vm_get_cbase(GET_ISEQ(), GET_LFP(), GET_DFP());
 	if (rb_cvar_defined(klass, SYM2ID(obj))) {
 	    expr_type = "class variable";
 	}
@@ -1141,7 +1113,7 @@
 {
     if (OPT_CHECKED_RUN) {
 	if (reg_cfp->sp != reg_cfp->bp) {
-	    rb_bug("Stack consistency error (sp: %d, bp: %d)",
+	    rb_bug("Stack consistency error (sp: %td, bp: %td)",
 		   VM_SP_CNT(th, reg_cfp->sp), VM_SP_CNT(th, reg_cfp->bp));
 	}
     }
@@ -1732,7 +1704,7 @@
 {
     if (FIXNUM_2_P(recv, obj) &&
 	BASIC_OP_UNREDEFINED_P(BOP_LT)) {
-	long a = FIX2LONG(recv), b = FIX2LONG(obj);
+	SIGNED_VALUE a = recv, b = obj;
 
 	if (a < b) {
 	    val = Qtrue;
@@ -1761,7 +1733,7 @@
 {
     if (FIXNUM_2_P(recv, obj) &&
 	BASIC_OP_UNREDEFINED_P(BOP_LE)) {
-	long a = FIX2LONG(recv), b = FIX2LONG(obj);
+	SIGNED_VALUE a = recv, b = obj;
 
 	if (a <= b) {
 	    val = Qtrue;
@@ -1791,7 +1763,7 @@
 {
     if (FIXNUM_2_P(recv, obj) &&
 	BASIC_OP_UNREDEFINED_P(BOP_GT)) {
-	long a = FIX2LONG(recv), b = FIX2LONG(obj);
+	SIGNED_VALUE a = recv, b = obj;
 
 	if (a > b) {
 	    val = Qtrue;
@@ -1820,7 +1792,7 @@
 {
     if (FIXNUM_2_P(recv, obj) &&
 	BASIC_OP_UNREDEFINED_P(BOP_GE)) {
-	long a = FIX2LONG(recv), b = FIX2LONG(obj);
+	SIGNED_VALUE a = recv, b = obj;
 
 	if (a >= b) {
 	    val = Qtrue;

Modified: MacRuby/branches/testing/instruby.rb
===================================================================
--- MacRuby/branches/testing/instruby.rb	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/instruby.rb	2008-06-05 08:33:02 UTC (rev 249)
@@ -489,6 +489,20 @@
   end
 end
 
+puts "fixing bridge support dylibs"
+unless File.exist?('markgc')
+  unless system("gcc markgc.c -std=gnu99 -o markgc")
+    $stderr.puts "cannot build the markgc tool"
+    exit 1
+  end
+end
+Dir.glob('/System/Library/Frameworks/**/BridgeSupport/*.dylib').each do |p|
+  unless system("./markgc '#{p}' >& /dev/null")
+    $stderr.puts "cannot markgc #{p}"
+    exit 1
+  end
+end
+
 end # unless $installing_rdoc
 
 # vi:set sw=2:

Modified: MacRuby/branches/testing/io.c
===================================================================
--- MacRuby/branches/testing/io.c	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/io.c	2008-06-05 08:33:02 UTC (rev 249)
@@ -2,7 +2,7 @@
 
   io.c -
 
-  $Author: akr $
+  $Author: mame $
   created at: Fri Oct 15 18:08:59 JST 1993
 
   Copyright (C) 1993-2007 Yukihiro Matsumoto
@@ -271,6 +271,7 @@
 rb_io_get_write_io(VALUE io)
 {
     VALUE write_io;
+    rb_io_check_initialized(RFILE(io)->fptr);
     write_io = RFILE(io)->fptr->tied_io_for_writing;
     if (write_io) {
         return write_io;
@@ -1388,9 +1389,9 @@
 {
     long bytes = 0;
     long n;
+#if !WITH_OBJC
     long pos = 0;
     rb_encoding *enc = io_input_encoding(fptr);
-#if !WITH_OBJC
     int cr = fptr->enc2 ? ENC_CODERANGE_BROKEN : 0;
 #endif
 
@@ -1746,7 +1747,9 @@
 	    const char *p = READ_DATA_PENDING_PTR(fptr);
 	    const char *e;
 	    long last = 0, len = (c != EOF);
+#if !WITH_OBJC
 	    rb_encoding *enc = io_read_encoding(fptr);
+#endif
 
 	    if (limit > 0 && pending > limit) pending = limit;
 	    e = memchr(p, delim, pending);
@@ -1808,7 +1811,14 @@
 	    rb_str_cat(str, &ch, 1);
 	}
 	else {
+#if WITH_OBJC
+	    char buf[2];
+	    buf[0] = ch;
+	    buf[1] = '\0';
+	    *strp = str = rb_str_new(buf, 1);
+#else
 	    *strp = str = rb_str_new(&ch, 1);
+#endif
 	}
     }
 
@@ -1842,9 +1852,9 @@
 {
     VALUE str = Qnil;
     int len = 0;
+#if !WITH_OBJC
     long pos = 0;
     rb_encoding *enc = io_input_encoding(fptr);
-#if !WITH_OBJC
     int cr = fptr->enc2 ? ENC_CODERANGE_BROKEN : 0;
 #endif
 
@@ -1897,7 +1907,9 @@
 prepare_getline_args(int argc, VALUE *argv, VALUE *rsp, long *limit, VALUE io)
 {
     VALUE lim, rs;
+#if !WITH_OBJC
     rb_io_t *fptr;
+#endif
 
     if (argc == 0) {
 	rs = rb_rs;
@@ -1999,7 +2011,7 @@
 
 	while ((c = appendline(fptr, newline, &str, &limit)) != EOF) {
 	    if (c == newline) {
-		const char *s, *p, *pp;
+		const char *s, *p;
 
 		if (RSTRING_LEN(str) < rslen) continue;
 		s = RSTRING_PTR(str);
@@ -2280,7 +2292,9 @@
 static VALUE
 io_getc(rb_io_t *fptr, rb_encoding *enc)
 {
+#if !WITH_OBJC
     int r, n, cr = 0;
+#endif
     VALUE str;
 
     if (io_fillbuf(fptr) < 0) {
@@ -2465,9 +2479,7 @@
 {
     int c;
 
-    if (!STDIO_READ_DATA_PENDING(f)) {
-	rb_thread_wait_fd(fileno(f));
-    }
+    rb_read_check(f);
     TRAP_BEG;
     c = getc(f);
     TRAP_END;
@@ -2581,7 +2593,10 @@
     if (FIXNUM_P(c)) {
 	int cc = FIX2INT(c);
 #if WITH_OBJC
-	c = rb_str_new((char *)&cc, 1);
+	char buf[2];
+	buf[0] = cc;
+	buf[1] = '\0';
+	c = rb_str_new(buf, 1);
 #else
 	rb_encoding *enc = io_read_encoding(fptr);
 	char buf[16];
@@ -5170,7 +5185,9 @@
 static void
 argf_mark(void *ptr)
 {
+#if !WITH_OBJC
     struct argf *p = ptr;
+#endif
     rb_gc_mark(p->filename);
     rb_gc_mark(p->current_file);
     rb_gc_mark(p->lineno);
@@ -6430,9 +6447,9 @@
     int close_src;
     int close_dst;
     off_t total;
-    char *syserr;
+    const char *syserr;
     int error_no;
-    char *notimp;
+    const char *notimp;
     rb_fdset_t fds;
     rb_thread_t *th;
 };
@@ -7027,13 +7044,19 @@
 static VALUE
 argf_external_encoding(VALUE argf)
 {
-    return rb_io_external_encoding(current_file);
+    if (!RTEST(current_file)) {
+	return rb_enc_from_encoding(rb_default_external_encoding());
+    }
+    return rb_io_external_encoding(rb_io_check_io(current_file));
 }
 
 static VALUE
 argf_internal_encoding(VALUE argf)
 {
-    return rb_io_internal_encoding(current_file);
+    if (!RTEST(current_file)) {
+	return rb_enc_from_encoding(rb_default_external_encoding());
+    }
+    return rb_io_internal_encoding(rb_io_check_io(current_file));
 }
 
 static VALUE
@@ -7272,7 +7295,7 @@
     VALUE ch;
 
   retry:
-    if (!next_argv()) return Qnil;
+    if (!next_argv()) rb_eof_error();
     if (TYPE(current_file) != T_FILE) {
 	ch = rb_funcall3(current_file, rb_intern("getc"), 0, 0);
     }
@@ -7733,6 +7756,9 @@
     rb_define_method(rb_cARGF, "each_line",  argf_each_line, -1);
     rb_define_method(rb_cARGF, "each_byte",  argf_each_byte, 0);
     rb_define_method(rb_cARGF, "each_char",  argf_each_char, 0);
+    rb_define_method(rb_cARGF, "lines", argf_each_line, -1);
+    rb_define_method(rb_cARGF, "bytes", argf_each_byte, 0);
+    rb_define_method(rb_cARGF, "chars", argf_each_char, 0);
 
     rb_define_method(rb_cARGF, "read",  argf_read, -1);
     rb_define_method(rb_cARGF, "readpartial",  argf_readpartial, -1);

Modified: MacRuby/branches/testing/iseq.c
===================================================================
--- MacRuby/branches/testing/iseq.c	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/iseq.c	2008-06-05 08:33:02 UTC (rev 249)
@@ -2,7 +2,7 @@
 
   iseq.c -
 
-  $Author: ko1 $
+  $Author: nobu $
   created at: 2006-07-11(Tue) 09:00:03 +0900
 
   Copyright (C) 2006 Koichi Sasada
@@ -184,7 +184,6 @@
       (struct iseq_compile_data_storage *)
 	ALLOC_N(char, INITIAL_ISEQ_COMPILE_DATA_STORAGE_BUFF_SIZE +
 		sizeof(struct iseq_compile_data_storage));
-    GC_WB(&iseq->compile_data->storage_head, iseq->compile_data->storage_head);
 
     GC_WB(&iseq->compile_data->catch_table_ary, rb_ary_new());
     iseq->compile_data->storage_head->pos = 0;
@@ -394,6 +393,7 @@
 	st_insert(type_map, ID2SYM(rb_intern("rescue")), ISEQ_TYPE_RESCUE);
 	st_insert(type_map, ID2SYM(rb_intern("ensure")), ISEQ_TYPE_ENSURE);
 	st_insert(type_map, ID2SYM(rb_intern("eval")), ISEQ_TYPE_EVAL);
+	st_insert(type_map, ID2SYM(rb_intern("defined_guard")), ISEQ_TYPE_DEFINED_GUARD);
     }
 
     if (st_lookup(type_map, type, &iseq_type) == 0) {
@@ -448,7 +448,7 @@
     rb_thread_t *th = GET_THREAD();
     make_compile_option(&option, opt);
 
-    if (th->base_block) {
+    if (th->base_block && th->base_block->iseq) {
 	return rb_iseq_new_with_opt(node, th->base_block->iseq->name,
 				    file, th->base_block->iseq->self,
 				    ISEQ_TYPE_EVAL, &option);
@@ -779,7 +779,7 @@
     return len;
 }
 
-static char *
+static const char *
 catch_type(int type)
 {
     switch (type) {
@@ -1007,6 +1007,7 @@
     DECL_SYMBOL(rescue);
     DECL_SYMBOL(ensure);
     DECL_SYMBOL(eval);
+    DECL_SYMBOL(defined_guard);
 
     if (sym_top == 0) {
 	int i;
@@ -1020,6 +1021,7 @@
 	INIT_SYMBOL(rescue);
 	INIT_SYMBOL(ensure);
 	INIT_SYMBOL(eval);
+	INIT_SYMBOL(defined_guard);
     }
 
     /* type */
@@ -1031,6 +1033,7 @@
       case ISEQ_TYPE_RESCUE: type = sym_rescue; break;
       case ISEQ_TYPE_ENSURE: type = sym_ensure; break;
       case ISEQ_TYPE_EVAL:   type = sym_eval;   break;
+      case ISEQ_TYPE_DEFINED_GUARD: type = sym_defined_guard; break;
       default: rb_bug("unsupported iseq type");
     };
 
@@ -1306,6 +1309,7 @@
 
     /* disable this feature because there is no verifier. */
     /* rb_define_singleton_method(rb_cISeq, "load", iseq_s_load, -1); */
+    (void)iseq_s_load;
 
     rb_define_singleton_method(rb_cISeq, "compile", iseq_s_compile, -1);
     rb_define_singleton_method(rb_cISeq, "new", iseq_s_compile, -1);

Modified: MacRuby/branches/testing/keywords
===================================================================
--- MacRuby/branches/testing/keywords	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/keywords	2008-06-05 08:33:02 UTC (rev 249)
@@ -1,5 +1,5 @@
 %{
-struct kwtable {char *name; int id[2]; enum lex_state_e state;};
+struct kwtable {const char *name; int id[2]; enum lex_state_e state;};
 const struct kwtable *rb_reserved_word(const char *, unsigned int);
 #ifndef RIPPER
 %}

Modified: MacRuby/branches/testing/lex.c.blt
===================================================================
--- MacRuby/branches/testing/lex.c.blt	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/lex.c.blt	2008-06-05 08:33:02 UTC (rev 249)
@@ -30,7 +30,7 @@
 
 #line 1 "keywords"
 
-struct kwtable {char *name; int id[2]; enum lex_state_e state;};
+struct kwtable {const char *name; int id[2]; enum lex_state_e state;};
 const struct kwtable *rb_reserved_word(const char *, unsigned int);
 #ifndef RIPPER
 #line 7 "keywords"

Modified: MacRuby/branches/testing/lex.c.src
===================================================================
--- MacRuby/branches/testing/lex.c.src	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/lex.c.src	2008-06-05 08:33:02 UTC (rev 249)
@@ -1,5 +1,5 @@
 %{
-struct kwtable {char *name; int id[2]; enum lex_state_e state;};
+struct kwtable {const char *name; int id[2]; enum lex_state_e state;};
 const struct kwtable *rb_reserved_word(const char *, unsigned int);
 #ifndef RIPPER
 %}

Copied: MacRuby/branches/testing/lib/cmath.rb (from rev 248, MacRuby/trunk/lib/cmath.rb)
===================================================================
--- MacRuby/branches/testing/lib/cmath.rb	                        (rev 0)
+++ MacRuby/branches/testing/lib/cmath.rb	2008-06-05 08:33:02 UTC (rev 249)
@@ -0,0 +1,223 @@
+module CMath
+
+  include Math
+
+  alias exp! exp
+  alias log! log
+  alias log10! log10
+  alias sqrt! sqrt
+
+  alias sin! sin
+  alias cos! cos
+  alias tan! tan
+
+  alias sinh! sinh
+  alias cosh! cosh
+  alias tanh! tanh
+
+  alias asin! asin
+  alias acos! acos
+  alias atan! atan
+  alias atan2! atan2
+
+  alias asinh! asinh
+  alias acosh! acosh
+  alias atanh! atanh
+
+  def exp(z)
+    if Complex.generic?(z)
+      exp!(z)
+    else
+      Complex(exp!(z.real) * cos!(z.image),
+	      exp!(z.real) * sin!(z.image))
+    end
+  end
+
+  def log(*args)
+    z, b = args
+    if Complex.generic?(z) and z >= 0 and (b.nil? or b >= 0)
+      log!(*args)
+    else
+      r, theta = z.polar
+      a = Complex(log!(r.abs), theta)
+      if b
+	a /= log(b)
+      end
+      a
+    end
+  end
+
+  def log10(z)
+    if Complex.generic?(z)
+      log10!(z)
+    else
+      log(z) / log!(10)
+    end
+  end
+
+  def sqrt(z)
+    if Complex.generic?(z)
+      if z >= 0
+	sqrt!(z)
+      else
+	Complex(0,sqrt!(-z))
+      end
+    else
+      if z.image < 0
+	sqrt(z.conjugate).conjugate
+      else
+	r = z.abs
+	x = z.real
+	Complex(sqrt!((r + x) / 2), sqrt!((r - x) / 2))
+      end
+    end
+  end
+
+  def sin(z)
+    if Complex.generic?(z)
+      sin!(z)
+    else
+      Complex(sin!(z.real) * cosh!(z.image),
+	      cos!(z.real) * sinh!(z.image))
+    end
+  end
+
+  def cos(z)
+    if Complex.generic?(z)
+      cos!(z)
+    else
+      Complex(cos!(z.real) * cosh!(z.image),
+	      -sin!(z.real) * sinh!(z.image))
+    end
+  end
+
+  def tan(z)
+    if Complex.generic?(z)
+      tan!(z)
+    else
+      sin(z)/cos(z)
+    end
+  end
+
+  def sinh(z)
+    if Complex.generic?(z)
+      sinh!(z)
+    else
+      Complex(sinh!(z.real) * cos!(z.image),
+	      cosh!(z.real) * sin!(z.image))
+    end
+  end
+
+  def cosh(z)
+    if Complex.generic?(z)
+      cosh!(z)
+    else
+      Complex(cosh!(z.real) * cos!(z.image),
+	      sinh!(z.real) * sin!(z.image))
+    end
+  end
+
+  def tanh(z)
+    if Complex.generic?(z)
+      tanh!(z)
+    else
+      sinh(z) / cosh(z)
+    end
+  end
+
+  def asin(z)
+    if Complex.generic?(z) and z >= -1 and z <= 1
+      asin!(z)
+    else
+      -1.0.im * log(1.0.im * z + sqrt(1.0 - z * z))
+    end
+  end
+
+  def acos(z)
+    if Complex.generic?(z) and z >= -1 and z <= 1
+      acos!(z)
+    else
+      -1.0.im * log(z + 1.0.im * sqrt(1.0 - z * z))
+    end
+  end
+
+  def atan(z)
+    if Complex.generic?(z)
+      atan!(z)
+    else
+      1.0.im * log((1.0.im + z) / (1.0.im - z)) / 2.0
+    end
+  end
+
+  def atan2(y,x)
+    if Complex.generic?(y) and Complex.generic?(x)
+      atan2!(y,x)
+    else
+      -1.0.im * log((x + 1.0.im * y) / sqrt(x * x + y * y))
+    end
+  end
+
+  def acosh(z)
+    if Complex.generic?(z) and z >= 1
+      acosh!(z)
+    else
+      log(z + sqrt(z * z - 1.0))
+    end
+  end
+
+  def asinh(z)
+    if Complex.generic?(z)
+      asinh!(z)
+    else
+      log(z + sqrt(1.0 + z * z))
+    end
+  end
+
+  def atanh(z)
+    if Complex.generic?(z) and z >= -1 and z <= 1
+      atanh!(z)
+    else
+      log((1.0 + z) / (1.0 - z)) / 2.0
+    end
+  end
+
+  module_function :exp!
+  module_function :exp
+  module_function :log!
+  module_function :log
+  module_function :log10!
+  module_function :log10
+  module_function :sqrt!
+  module_function :sqrt
+
+  module_function :sin!
+  module_function :sin
+  module_function :cos!
+  module_function :cos
+  module_function :tan!
+  module_function :tan
+
+  module_function :sinh!
+  module_function :sinh
+  module_function :cosh!
+  module_function :cosh
+  module_function :tanh!
+  module_function :tanh
+
+  module_function :asin!
+  module_function :asin
+  module_function :acos!
+  module_function :acos
+  module_function :atan!
+  module_function :atan
+  module_function :atan2!
+  module_function :atan2
+
+  module_function :asinh!
+  module_function :asinh
+  module_function :acosh!
+  module_function :acosh
+  module_function :atanh!
+  module_function :atanh
+
+end

Modified: MacRuby/branches/testing/lib/delegate.rb
===================================================================
--- MacRuby/branches/testing/lib/delegate.rb	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/lib/delegate.rb	2008-06-05 08:33:02 UTC (rev 249)
@@ -153,9 +153,9 @@
     # Checks for a method provided by this the delegate object by fowarding the 
     # call through \_\_getobj\_\_.
     # 
-    def respond_to?(m)
+    def respond_to?(m, include_private = false)
       return true if super
-      return self.__getobj__.respond_to?(m)
+      return self.__getobj__.respond_to?(m, include_private)
     end
 
     # 

Modified: MacRuby/branches/testing/lib/erb.rb
===================================================================
--- MacRuby/branches/testing/lib/erb.rb	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/lib/erb.rb	2008-06-05 08:33:02 UTC (rev 249)
@@ -236,7 +236,7 @@
 # Rails, the web application framework, uses ERB to create views.
 #
 class ERB
-  Revision = '$Date:: 2008-04-30 05:40:52 -0700#$' 	#'
+  Revision = '$Date:: 2008-06-02 00:15:12 -0700#$' 	#'
 
   # Returns revision information for the erb.rb module.
   def self.version

Deleted: MacRuby/branches/testing/lib/generator.rb
===================================================================
--- MacRuby/branches/testing/lib/generator.rb	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/lib/generator.rb	2008-06-05 08:33:02 UTC (rev 249)
@@ -1,385 +0,0 @@
-#!/usr/bin/env ruby
-#--
-# $Idaemons: /home/cvs/rb/generator.rb,v 1.8 2001/10/03 08:54:32 knu Exp $
-# $RoughId: generator.rb,v 1.10 2003/10/14 19:36:58 knu Exp $
-# $Id: generator.rb 11708 2007-02-12 23:01:19Z shyouhei $
-#++
-#
-# = generator.rb: convert an internal iterator to an external one
-#
-# Copyright (c) 2001,2003 Akinori MUSHA <knu at iDaemons.org>
-#
-# All rights reserved.  You can redistribute and/or modify it under
-# the same terms as Ruby.
-#
-# == Overview
-#
-# This library provides the Generator class, which converts an
-# internal iterator (i.e. an Enumerable object) to an external
-# iterator.  In that form, you can roll many iterators independently.
-#
-# The SyncEnumerator class, which is implemented using Generator,
-# makes it easy to roll many Enumerable objects synchronously.
-#
-# See the respective classes for examples of usage.
-
-
-#
-# Generator converts an internal iterator (i.e. an Enumerable object)
-# to an external iterator.
-#
-# == Example
-#
-#   require 'generator'
-#
-#   # Generator from an Enumerable object
-#   g = Generator.new(['A', 'B', 'C', 'Z'])
-#
-#   while g.next?
-#     puts g.next
-#   end
-#
-#   # Generator from a block
-#   g = Generator.new { |g|
-#     for i in 'A'..'C'
-#       g.yield i
-#     end
-#
-#     g.yield 'Z'
-#   }
-#
-#   # The same result as above
-#   while g.next?
-#     puts g.next
-#   end
-#   
-class Generator
-  include Enumerable
-
-  # Creates a new generator either from an Enumerable object or from a
-  # block.
-  #
-  # In the former, block is ignored even if given.
-  #
-  # In the latter, the given block is called with the generator
-  # itself, and expected to call the +yield+ method for each element.
-  def initialize(enum = nil, &block)
-    if enum
-      @block = proc{|g| enum.each{|value| g.yield value}}
-    else
-      @block = block
-    end
-    @index = 0
-    @queue = []
-    @main_thread = nil
-    @loop_thread.kill if defined?(@loop_thread)
-    @loop_thread = Thread.new do
-      Thread.stop
-      begin
-        @block.call(self)
-      rescue
-        @main_thread.raise $!
-      ensure
-        @main_thread.wakeup
-      end
-    end
-    Thread.pass until @loop_thread.stop?
-    self
-  end
-
-  # Yields an element to the generator.
-  def yield(value)
-    if Thread.current != @loop_thread
-      raise "should be called in Generator.new{|g| ... }"
-    end
-    Thread.critical = true
-    begin
-      @queue << value
-      @main_thread.wakeup
-      Thread.stop
-    ensure
-      Thread.critical = false
-    end
-    self
-  end
-
-  # Returns true if the generator has reached the end.
-  def end?
-    if @queue.empty?
-      if @main_thread
-        raise "should not be called in Generator.new{|g| ... }"
-      end
-      Thread.critical = true
-      begin
-        @main_thread = Thread.current
-        @loop_thread.wakeup
-        Thread.stop
-      rescue ThreadError
-        # ignore
-      ensure
-        @main_thread = nil
-        Thread.critical = false
-      end
-    end
-    @queue.empty?
-  end
-
-  # Returns true if the generator has not reached the end yet.
-  def next?
-    !end?
-  end
-
-  # Returns the current index (position) counting from zero.
-  def index
-    @index
-  end
-
-  # Returns the current index (position) counting from zero.
-  def pos
-    @index
-  end
-
-  # Returns the element at the current position and moves forward.
-  def next
-    raise EOFError.new("no more elements available") if end?
-    @index += 1
-    @queue.shift
-  end
-
-  # Returns the element at the current position.
-  def current
-    raise EOFError.new("no more elements available") if end?
-    @queue.first
-  end
-
-  # Rewinds the generator.
-  def rewind
-    initialize(nil, &@block) if @index.nonzero?
-    self
-  end
-
-  # Rewinds the generator and enumerates the elements.
-  def each
-    rewind
-    until end?
-      yield self.next
-    end
-    self
-  end
-end
-
-#
-# SyncEnumerator creates an Enumerable object from multiple Enumerable
-# objects and enumerates them synchronously.
-#
-# == Example
-#
-#   require 'generator'
-#
-#   s = SyncEnumerator.new([1,2,3], ['a', 'b', 'c'])
-#
-#   # Yields [1, 'a'], [2, 'b'], and [3,'c']
-#   s.each { |row| puts row.join(', ') }
-#
-class SyncEnumerator
-  include Enumerable
-
-  # Creates a new SyncEnumerator which enumerates rows of given
-  # Enumerable objects.
-  def initialize(*enums)
-    @gens = enums.map { |e| Generator.new(e) }
-  end
-
-  # Returns the number of enumerated Enumerable objects, i.e. the size
-  # of each row.
-  def size
-    @gens.size
-  end
-
-  # Returns the number of enumerated Enumerable objects, i.e. the size
-  # of each row.
-  def length
-    @gens.length
-  end
-
-  # Returns true if the given nth Enumerable object has reached the
-  # end.  If no argument is given, returns true if any of the
-  # Enumerable objects has reached the end.
-  def end?(i = nil)
-    if i.nil?
-      @gens.detect { |g| g.end? } ? true : false
-    else
-      @gens[i].end?
-    end
-  end
-
-  # Enumerates rows of the Enumerable objects.
-  def each
-    @gens.each { |g| g.rewind }
-
-    loop do
-      count = 0
-
-      ret = @gens.map { |g|
-	if g.end?
-	  count += 1
-	  nil
-	else
-	  g.next
-	end
-      }
-
-      if count == @gens.size
-	break
-      end
-
-      yield ret
-    end
-
-    self
-  end
-end
-
-if $0 == __FILE__
-  eval DATA.read, nil, $0, __LINE__+4
-end
-
-__END__
-
-__END__
-
-require 'test/unit'
-
-class TC_Generator < Test::Unit::TestCase
-  def test_block1
-    g = Generator.new { |g|
-      # no yield's
-    }
-
-    assert_equal(0, g.pos)
-    assert_raises(EOFError) { g.current }
-  end
-
-  def test_block2
-    g = Generator.new { |g|
-      for i in 'A'..'C'
-        g.yield i
-      end
-
-      g.yield 'Z'
-    }
-
-    assert_equal(0, g.pos)
-    assert_equal('A', g.current)
-
-    assert_equal(true, g.next?)
-    assert_equal(0, g.pos)
-    assert_equal('A', g.current)
-    assert_equal(0, g.pos)
-    assert_equal('A', g.next)
-
-    assert_equal(1, g.pos)
-    assert_equal(true, g.next?)
-    assert_equal(1, g.pos)
-    assert_equal('B', g.current)
-    assert_equal(1, g.pos)
-    assert_equal('B', g.next)
-
-    assert_equal(g, g.rewind)
-
-    assert_equal(0, g.pos)
-    assert_equal('A', g.current)
-
-    assert_equal(true, g.next?)
-    assert_equal(0, g.pos)
-    assert_equal('A', g.current)
-    assert_equal(0, g.pos)
-    assert_equal('A', g.next)
-
-    assert_equal(1, g.pos)
-    assert_equal(true, g.next?)
-    assert_equal(1, g.pos)
-    assert_equal('B', g.current)
-    assert_equal(1, g.pos)
-    assert_equal('B', g.next)
-
-    assert_equal(2, g.pos)
-    assert_equal(true, g.next?)
-    assert_equal(2, g.pos)
-    assert_equal('C', g.current)
-    assert_equal(2, g.pos)
-    assert_equal('C', g.next)
-
-    assert_equal(3, g.pos)
-    assert_equal(true, g.next?)
-    assert_equal(3, g.pos)
-    assert_equal('Z', g.current)
-    assert_equal(3, g.pos)
-    assert_equal('Z', g.next)
-
-    assert_equal(4, g.pos)
-    assert_equal(false, g.next?)
-    assert_raises(EOFError) { g.next }
-  end
-
-  def test_each
-    a = [5, 6, 7, 8, 9]
-
-    g = Generator.new(a)
-
-    i = 0
-
-    g.each { |x|
-      assert_equal(a[i], x)
-
-      i += 1
-
-      break if i == 3
-    }
-
-    assert_equal(3, i)
-
-    i = 0
-
-    g.each { |x|
-      assert_equal(a[i], x)
-
-      i += 1
-    }
-
-    assert_equal(5, i)
-  end
-end
-
-class TC_SyncEnumerator < Test::Unit::TestCase
-  def test_each
-    r = ['a'..'f', 1..10, 10..20]
-    ra = r.map { |x| x.to_a }
-
-    a = (0...(ra.map {|x| x.size}.max)).map { |i| ra.map { |x| x[i] } }
-
-    s = SyncEnumerator.new(*r)
-
-    i = 0
-
-    s.each { |x|
-      assert_equal(a[i], x)
-
-      i += 1
-
-      break if i == 3
-    }
-
-    assert_equal(3, i)
-
-    i = 0
-
-    s.each { |x|
-      assert_equal(a[i], x)
-
-      i += 1
-    }
-
-    assert_equal(a.size, i)
-  end
-end

Modified: MacRuby/branches/testing/lib/net/imap.rb
===================================================================
--- MacRuby/branches/testing/lib/net/imap.rb	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/lib/net/imap.rb	2008-06-05 08:33:02 UTC (rev 249)
@@ -936,6 +936,7 @@
       @continuation_request_arrival = new_cond
       @logout_command_tag = nil
       @debug_output_bol = true
+      @exception = nil
 
       @greeting = get_response
       if @greeting.name == "BYE"
@@ -951,14 +952,24 @@
 
     def receive_responses
       while true
+        synchronize do
+          @exception = nil
+        end
         begin
           resp = get_response
-        rescue Exception
-          @sock.close
-          @client_thread.raise($!)
+        rescue Exception => e
+          synchronize do
+            @sock.close
+            @exception = e
+          end
           break
         end
-        break unless resp
+        unless resp
+          synchronize do
+            @exception = EOFError.new("end of file reached")
+          end
+          break
+        end
         begin
           synchronize do
             case resp
@@ -976,7 +987,8 @@
               end
               if resp.name == "BYE" && @logout_command_tag.nil?
                 @sock.close
-                raise ByeResponseError, resp.raw_data
+                @exception = ByeResponseError.new(resp.raw_data)
+                break
               end
             when ContinuationRequest
               @continuation_request_arrival.signal
@@ -985,14 +997,23 @@
               handler.call(resp)
             end
           end
-        rescue Exception
-          @client_thread.raise($!)
+        rescue Exception => e
+          @exception = e
+          synchronize do
+            @tagged_response_arrival.broadcast
+            @continuation_request_arrival.broadcast
+          end
         end
       end
+      synchronize do
+        @tagged_response_arrival.broadcast
+        @continuation_request_arrival.broadcast
+      end
     end
 
     def get_tagged_response(tag, cmd)
       until @tagged_responses.key?(tag)
+        raise @exception if @exception
         @tagged_response_arrival.wait
       end
       resp = @tagged_responses.delete(tag)
@@ -1119,6 +1140,7 @@
     def send_literal(str)
       put_string("{" + str.length.to_s + "}" + CRLF)
       @continuation_request_arrival.wait
+      raise @exception if @exception
       put_string(str)
     end
 

Modified: MacRuby/branches/testing/lib/rake.rb
===================================================================
--- MacRuby/branches/testing/lib/rake.rb	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/lib/rake.rb	2008-06-05 08:33:02 UTC (rev 249)
@@ -1088,8 +1088,9 @@
 # other objects.
 
 include RakeFileUtils
-private(*FileUtils.instance_methods(false))
-private(*RakeFileUtils.instance_methods(false))
+# FIXME: this doesn't work in MacRuby yet
+#private(*FileUtils.instance_methods(false))
+#private(*RakeFileUtils.instance_methods(false))
 
 ######################################################################
 module Rake
@@ -1167,23 +1168,21 @@
     # Now do the delegation.
     DELEGATING_METHODS.each_with_index do |sym, i|
       if SPECIAL_RETURN.include?(sym)
-        ln = __LINE__+1
-        class_eval %{
-          def #{sym}(*args, &block)
+        class_eval do
+	  define_method(sym) do |*args, &block|
             resolve
-            result = @items.send(:#{sym}, *args, &block)
+            result = @items.send(sym, *args, &block)
             FileList.new.import(result)
           end
-        }, __FILE__, ln
+        end
       else
-        ln = __LINE__+1
-        class_eval %{
-          def #{sym}(*args, &block)
+        class_eval do
+	  define_method(sym) do |*args, &block|
             resolve
-            result = @items.send(:#{sym}, *args, &block)
+            result = @items.send(sym, *args, &block)
             result.object_id == @items.object_id ? self : result
-          end
-        }, __FILE__, ln
+          end 
+        end
       end
     end
 

Deleted: MacRuby/branches/testing/lib/require_relative.rb
===================================================================
--- MacRuby/branches/testing/lib/require_relative.rb	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/lib/require_relative.rb	2008-06-05 08:33:02 UTC (rev 249)
@@ -1,11 +0,0 @@
-def require_relative(relative_feature)
-  c = caller.first
-  e = c.rindex(/:\d+:in /)
-  file = $`
-  if /\A\((.*)\)/ =~ file # eval, etc.
-    raise LoadError, "require_relative is called in #{$1}"
-  end
-  absolute_feature = File.expand_path(File.join(File.dirname(file), relative_feature))
-  require absolute_feature
-end
-

Deleted: MacRuby/branches/testing/lib/rubygems/gem_open_uri.rb
===================================================================
--- MacRuby/branches/testing/lib/rubygems/gem_open_uri.rb	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/lib/rubygems/gem_open_uri.rb	2008-06-05 08:33:02 UTC (rev 249)
@@ -1,7 +0,0 @@
-#!/usr/bin/env ruby
-
-if RUBY_VERSION > '1.9' then
-  require 'open-uri'
-else
-  require 'rubygems/open-uri'
-end

Deleted: MacRuby/branches/testing/lib/rubygems/open-uri.rb
===================================================================
--- MacRuby/branches/testing/lib/rubygems/open-uri.rb	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/lib/rubygems/open-uri.rb	2008-06-05 08:33:02 UTC (rev 249)
@@ -1,773 +0,0 @@
-require 'uri'
-require 'stringio'
-require 'time'
-
-# :stopdoc:
-module Kernel
-  private
-  alias rubygems_open_uri_original_open open # :nodoc:
-
-  # makes possible to open various resources including URIs.
-  # If the first argument respond to `open' method,
-  # the method is called with the rest arguments.
-  #
-  # If the first argument is a string which begins with xxx://,
-  # it is parsed by URI.parse.  If the parsed object respond to `open' method,
-  # the method is called with the rest arguments.
-  #
-  # Otherwise original open is called.
-  #
-  # Since open-uri.rb provides URI::HTTP#open, URI::HTTPS#open and
-  # URI::FTP#open,
-  # Kernel[#.]open can accepts such URIs and strings which begins with
-  # http://, https:// and ftp://.
-  # In these case, the opened file object is extended by OpenURI::Meta.
-  def open(name, *rest, &block) # :doc:
-    if name.respond_to?(:open)
-      name.open(*rest, &block)
-    elsif name.respond_to?(:to_str) &&
-          %r{\A[A-Za-z][A-Za-z0-9+\-\.]*://} =~ name &&
-          (uri = URI.parse(name)).respond_to?(:open)
-      uri.open(*rest, &block)
-    else
-      rubygems_open_uri_original_open(name, *rest, &block)
-    end
-  end
-  module_function :open
-end
-
-# OpenURI is an easy-to-use wrapper for net/http, net/https and net/ftp.
-#
-#== Example
-#
-# It is possible to open http/https/ftp URL as usual like opening a file:
-#
-#   open("http://www.ruby-lang.org/") {|f|
-#     f.each_line {|line| p line}
-#   }
-#
-# The opened file has several methods for meta information as follows since
-# it is extended by OpenURI::Meta.
-#
-#   open("http://www.ruby-lang.org/en") {|f|
-#     f.each_line {|line| p line}
-#     p f.base_uri         # <URI::HTTP:0x40e6ef2 URL:http://www.ruby-lang.org/en/>
-#     p f.content_type     # "text/html"
-#     p f.charset          # "iso-8859-1"
-#     p f.content_encoding # []
-#     p f.last_modified    # Thu Dec 05 02:45:02 UTC 2002
-#   }
-#
-# Additional header fields can be specified by an optional hash argument.
-#
-#   open("http://www.ruby-lang.org/en/",
-#     "User-Agent" => "Ruby/#{RUBY_VERSION}",
-#     "From" => "foo at bar.invalid",
-#     "Referer" => "http://www.ruby-lang.org/") {|f|
-#     # ...
-#   }
-#
-# The environment variables such as http_proxy, https_proxy and ftp_proxy
-# are in effect by default.  :proxy => nil disables proxy.
-#
-#   open("http://www.ruby-lang.org/en/raa.html", :proxy => nil) {|f|
-#     # ...
-#   }
-#
-# URI objects can be opened in a similar way.
-#
-#   uri = URI.parse("http://www.ruby-lang.org/en/")
-#   uri.open {|f|
-#     # ...
-#   }
-#
-# URI objects can be read directly. The returned string is also extended by
-# OpenURI::Meta.
-#
-#   str = uri.read
-#   p str.base_uri
-#
-# Author:: Tanaka Akira <akr at m17n.org>
-
-module OpenURI
-  Options = {
-    :proxy => true,
-    :proxy_http_basic_authentication => true,
-    :progress_proc => true,
-    :content_length_proc => true,
-    :http_basic_authentication => true,
-    :read_timeout => true,
-    :ssl_ca_cert => nil,
-    :ssl_verify_mode => nil,
-  }
-
-  def OpenURI.check_options(options) # :nodoc:
-    options.each {|k, v|
-      next unless Symbol === k
-      unless Options.include? k
-        raise ArgumentError, "unrecognized option: #{k}"
-      end
-    }
-  end
-
-  def OpenURI.scan_open_optional_arguments(*rest) # :nodoc:
-    if !rest.empty? && (String === rest.first || Integer === rest.first)
-      mode = rest.shift
-      if !rest.empty? && Integer === rest.first
-        perm = rest.shift
-      end
-    end
-    return mode, perm, rest
-  end
-
-  def OpenURI.open_uri(name, *rest) # :nodoc:
-    uri = URI::Generic === name ? name : URI.parse(name)
-    mode, perm, rest = OpenURI.scan_open_optional_arguments(*rest)
-    options = rest.shift if !rest.empty? && Hash === rest.first
-    raise ArgumentError.new("extra arguments") if !rest.empty?
-    options ||= {}
-    OpenURI.check_options(options)
-
-    unless mode == nil ||
-           mode == 'r' || mode == 'rb' ||
-           mode == File::RDONLY
-      raise ArgumentError.new("invalid access mode #{mode} (#{uri.class} resource is read only.)")
-    end
-
-    io = open_loop(uri, options)
-    if block_given?
-      begin
-        yield io
-      ensure
-        io.close
-      end
-    else
-      io
-    end
-  end
-
-  def OpenURI.open_loop(uri, options) # :nodoc:
-    proxy_opts = []
-    proxy_opts << :proxy_http_basic_authentication if options.include? :proxy_http_basic_authentication
-    proxy_opts << :proxy if options.include? :proxy
-    proxy_opts.compact!
-    if 1 < proxy_opts.length
-      raise ArgumentError, "multiple proxy options specified"
-    end
-    case proxy_opts.first
-    when :proxy_http_basic_authentication
-      opt_proxy, proxy_user, proxy_pass = options.fetch(:proxy_http_basic_authentication)
-      proxy_user = proxy_user.to_str
-      proxy_pass = proxy_pass.to_str
-      if opt_proxy == true
-        raise ArgumentError.new("Invalid authenticated proxy option: #{options[:proxy_http_basic_authentication].inspect}")
-      end
-    when :proxy
-      opt_proxy = options.fetch(:proxy)
-      proxy_user = nil
-      proxy_pass = nil
-    when nil
-      opt_proxy = true
-      proxy_user = nil
-      proxy_pass = nil
-    end
-    case opt_proxy
-    when true
-      find_proxy = lambda {|u| pxy = u.find_proxy; pxy ? [pxy, nil, nil] : nil}
-    when nil, false
-      find_proxy = lambda {|u| nil}
-    when String
-      opt_proxy = URI.parse(opt_proxy)
-      find_proxy = lambda {|u| [opt_proxy, proxy_user, proxy_pass]}
-    when URI::Generic
-      find_proxy = lambda {|u| [opt_proxy, proxy_user, proxy_pass]}
-    else
-      raise ArgumentError.new("Invalid proxy option: #{opt_proxy}")
-    end
-
-    uri_set = {}
-    buf = nil
-    while true
-      redirect = catch(:open_uri_redirect) {
-        buf = Buffer.new
-        uri.buffer_open(buf, find_proxy.call(uri), options)
-        nil
-      }
-      if redirect
-        if redirect.relative?
-          # Although it violates RFC2616, Location: field may have relative
-          # URI.  It is converted to absolute URI using uri as a base URI.
-          redirect = uri + redirect
-        end
-        unless OpenURI.redirectable?(uri, redirect)
-          raise "redirection forbidden: #{uri} -> #{redirect}"
-        end
-        if options.include? :http_basic_authentication
-          # send authentication only for the URI directly specified.
-          options = options.dup
-          options.delete :http_basic_authentication
-        end
-        uri = redirect
-        raise "HTTP redirection loop: #{uri}" if uri_set.include? uri.to_s
-        uri_set[uri.to_s] = true
-      else
-        break
-      end
-    end
-    io = buf.io
-    io.base_uri = uri
-    io
-  end
-
-  def OpenURI.redirectable?(uri1, uri2) # :nodoc:
-    # This test is intended to forbid a redirection from http://... to
-    # file:///etc/passwd.
-    # However this is ad hoc.  It should be extensible/configurable.
-    uri1.scheme.downcase == uri2.scheme.downcase ||
-    (/\A(?:http|ftp)\z/i =~ uri1.scheme && /\A(?:http|ftp)\z/i =~ uri2.scheme)
-  end
-
-  def OpenURI.open_http(buf, target, proxy, options) # :nodoc:
-    if proxy
-      proxy_uri, proxy_user, proxy_pass = proxy
-      raise "Non-HTTP proxy URI: #{proxy_uri}" if proxy_uri.class != URI::HTTP
-    end
-
-    if target.userinfo && "1.9.0" <= RUBY_VERSION
-      # don't raise for 1.8 because compatibility.
-      raise ArgumentError, "userinfo not supported.  [RFC3986]"
-    end
-
-    header = {}
-    options.each {|k, v| header[k] = v if String === k }
-
-    require 'net/http'
-    klass = Net::HTTP
-    if URI::HTTP === target
-      # HTTP or HTTPS
-      if proxy
-        if proxy_user && proxy_pass
-          klass = Net::HTTP::Proxy(proxy_uri.host, proxy_uri.port, proxy_user, proxy_pass)
-        else
-          klass = Net::HTTP::Proxy(proxy_uri.host, proxy_uri.port)
-        end
-      end
-      target_host = target.host
-      target_port = target.port
-      request_uri = target.request_uri
-    else
-      # FTP over HTTP proxy
-      target_host = proxy_uri.host
-      target_port = proxy_uri.port
-      request_uri = target.to_s
-      if proxy_user && proxy_pass
-        header["Proxy-Authorization"] = 'Basic ' + ["#{proxy_user}:#{proxy_pass}"].pack('m').delete("\r\n")
-      end
-    end
-
-    http = klass.new(target_host, target_port)
-    if target.class == URI::HTTPS
-      require 'net/https'
-      http.use_ssl = true
-      http.verify_mode = options[:ssl_verify_mode] || OpenSSL::SSL::VERIFY_PEER
-      store = OpenSSL::X509::Store.new
-      if options[:ssl_ca_cert]
-        if File.directory? options[:ssl_ca_cert]
-          store.add_path options[:ssl_ca_cert]
-        else
-          store.add_file options[:ssl_ca_cert]
-        end
-      else
-        store.set_default_paths
-      end
-      store.set_default_paths
-      http.cert_store = store
-    end
-    if options.include? :read_timeout
-      http.read_timeout = options[:read_timeout]
-    end
-
-    resp = nil
-    http.start {
-      if target.class == URI::HTTPS
-        # xxx: information hiding violation
-        sock = http.instance_variable_get(:@socket)
-        if sock.respond_to?(:io)
-          sock = sock.io # 1.9
-        else
-          sock = sock.instance_variable_get(:@socket) # 1.8
-        end
-        sock.post_connection_check(target_host)
-      end
-      req = Net::HTTP::Get.new(request_uri, header)
-      if options.include? :http_basic_authentication
-        user, pass = options[:http_basic_authentication]
-        req.basic_auth user, pass
-      end
-      http.request(req) {|response|
-        resp = response
-        if options[:content_length_proc] && Net::HTTPSuccess === resp
-          if resp.key?('Content-Length')
-            options[:content_length_proc].call(resp['Content-Length'].to_i)
-          else
-            options[:content_length_proc].call(nil)
-          end
-        end
-        resp.read_body {|str|
-          buf << str
-          if options[:progress_proc] && Net::HTTPSuccess === resp
-            options[:progress_proc].call(buf.size)
-          end
-        }
-      }
-    }
-    io = buf.io
-    io.rewind
-    io.status = [resp.code, resp.message]
-    resp.each {|name,value| buf.io.meta_add_field name, value }
-    case resp
-    when Net::HTTPSuccess
-    when Net::HTTPMovedPermanently, # 301
-         Net::HTTPFound, # 302
-         Net::HTTPSeeOther, # 303
-         Net::HTTPTemporaryRedirect # 307
-      throw :open_uri_redirect, URI.parse(resp['location'])
-    else
-      raise OpenURI::HTTPError.new(io.status.join(' '), io)
-    end
-  end
-
-  class HTTPError < StandardError
-    def initialize(message, io)
-      super(message)
-      @io = io
-    end
-    attr_reader :io
-  end
-
-  class Buffer # :nodoc:
-    def initialize
-      @io = StringIO.new
-      @size = 0
-    end
-    attr_reader :size
-
-    StringMax = 10240
-    def <<(str)
-      @io << str
-      @size += str.length
-      if StringIO === @io && StringMax < @size
-        require 'tempfile'
-        io = Tempfile.new('open-uri')
-        io.binmode
-        Meta.init io, @io if @io.respond_to? :meta
-        io << @io.string
-        @io = io
-      end
-    end
-
-    def io
-      Meta.init @io unless @io.respond_to? :meta
-      @io
-    end
-  end
-
-  # Mixin for holding meta-information.
-  module Meta
-    def Meta.init(obj, src=nil) # :nodoc:
-      obj.extend Meta
-      obj.instance_eval {
-        @base_uri = nil
-        @meta = {}
-      }
-      if src
-        obj.status = src.status
-        obj.base_uri = src.base_uri
-        src.meta.each {|name, value|
-          obj.meta_add_field(name, value)
-        }
-      end
-    end
-
-    # returns an Array which consists status code and message.
-    attr_accessor :status
-
-    # returns a URI which is base of relative URIs in the data.
-    # It may differ from the URI supplied by a user because redirection.
-    attr_accessor :base_uri
-
-    # returns a Hash which represents header fields.
-    # The Hash keys are downcased for canonicalization.
-    attr_reader :meta
-
-    def meta_add_field(name, value) # :nodoc:
-      @meta[name.downcase] = value
-    end
-
-    # returns a Time which represents Last-Modified field.
-    def last_modified
-      if v = @meta['last-modified']
-        Time.httpdate(v)
-      else
-        nil
-      end
-    end
-
-    RE_LWS = /[\r\n\t ]+/n
-    RE_TOKEN = %r{[^\x00- ()<>@,;:\\"/\[\]?={}\x7f]+}n
-    RE_QUOTED_STRING = %r{"(?:[\r\n\t !#-\[\]-~\x80-\xff]|\\[\x00-\x7f])*"}n
-    RE_PARAMETERS = %r{(?:;#{RE_LWS}?#{RE_TOKEN}#{RE_LWS}?=#{RE_LWS}?(?:#{RE_TOKEN}|#{RE_QUOTED_STRING})#{RE_LWS}?)*}n
-
-    def content_type_parse # :nodoc:
-      v = @meta['content-type']
-      # The last (?:;#{RE_LWS}?)? matches extra ";" which violates RFC2045.
-      if v && %r{\A#{RE_LWS}?(#{RE_TOKEN})#{RE_LWS}?/(#{RE_TOKEN})#{RE_LWS}?(#{RE_PARAMETERS})(?:;#{RE_LWS}?)?\z}no =~ v
-        type = $1.downcase
-        subtype = $2.downcase
-        parameters = []
-        $3.scan(/;#{RE_LWS}?(#{RE_TOKEN})#{RE_LWS}?=#{RE_LWS}?(?:(#{RE_TOKEN})|(#{RE_QUOTED_STRING}))/no) {|att, val, qval|
-          val = qval.gsub(/[\r\n\t !#-\[\]-~\x80-\xff]+|(\\[\x00-\x7f])/n) { $1 ? $1[1,1] : $& } if qval
-          parameters << [att.downcase, val]
-        }
-        ["#{type}/#{subtype}", *parameters]
-      else
-        nil
-      end
-    end
-
-    # returns "type/subtype" which is MIME Content-Type.
-    # It is downcased for canonicalization.
-    # Content-Type parameters are stripped.
-    def content_type
-      type, *parameters = content_type_parse
-      type || 'application/octet-stream'
-    end
-
-    # returns a charset parameter in Content-Type field.
-    # It is downcased for canonicalization.
-    #
-    # If charset parameter is not given but a block is given,
-    # the block is called and its result is returned.
-    # It can be used to guess charset.
-    #
-    # If charset parameter and block is not given,
-    # nil is returned except text type in HTTP.
-    # In that case, "iso-8859-1" is returned as defined by RFC2616 3.7.1.
-    def charset
-      type, *parameters = content_type_parse
-      if pair = parameters.assoc('charset')
-        pair.last.downcase
-      elsif block_given?
-        yield
-      elsif type && %r{\Atext/} =~ type &&
-            @base_uri && /\Ahttp\z/i =~ @base_uri.scheme
-        "iso-8859-1" # RFC2616 3.7.1
-      else
-        nil
-      end
-    end
-
-    # returns a list of encodings in Content-Encoding field
-    # as an Array of String.
-    # The encodings are downcased for canonicalization.
-    def content_encoding
-      v = @meta['content-encoding']
-      if v && %r{\A#{RE_LWS}?#{RE_TOKEN}#{RE_LWS}?(?:,#{RE_LWS}?#{RE_TOKEN}#{RE_LWS}?)*}o =~ v
-        v.scan(RE_TOKEN).map {|content_coding| content_coding.downcase}
-      else
-        []
-      end
-    end
-  end
-
-  # Mixin for HTTP and FTP URIs.
-  module OpenRead
-    # OpenURI::OpenRead#open provides `open' for URI::HTTP and URI::FTP.
-    #
-    # OpenURI::OpenRead#open takes optional 3 arguments as:
-    # OpenURI::OpenRead#open([mode [, perm]] [, options]) [{|io| ... }]
-    #
-    # `mode', `perm' is same as Kernel#open.
-    #
-    # However, `mode' must be read mode because OpenURI::OpenRead#open doesn't
-    # support write mode (yet).
-    # Also `perm' is just ignored because it is meaningful only for file
-    # creation.
-    #
-    # `options' must be a hash.
-    #
-    # Each pairs which key is a string in the hash specify a extra header
-    # field for HTTP.
-    # I.e. it is ignored for FTP without HTTP proxy.
-    #
-    # The hash may include other options which key is a symbol:
-    #
-    # [:proxy]
-    #  Synopsis:
-    #    :proxy => "http://proxy.foo.com:8000/"
-    #    :proxy => URI.parse("http://proxy.foo.com:8000/")
-    #    :proxy => true
-    #    :proxy => false
-    #    :proxy => nil
-    #   
-    #  If :proxy option is specified, the value should be String, URI,
-    #  boolean or nil.
-    #  When String or URI is given, it is treated as proxy URI.
-    #  When true is given or the option itself is not specified,
-    #  environment variable `scheme_proxy' is examined.
-    #  `scheme' is replaced by `http', `https' or `ftp'.
-    #  When false or nil is given, the environment variables are ignored and
-    #  connection will be made to a server directly.
-    #
-    # [:proxy_http_basic_authentication]
-    #  Synopsis:
-    #    :proxy_http_basic_authentication => ["http://proxy.foo.com:8000/", "proxy-user", "proxy-password"]
-    #    :proxy_http_basic_authentication => [URI.parse("http://proxy.foo.com:8000/"), "proxy-user", "proxy-password"]
-    #   
-    #  If :proxy option is specified, the value should be an Array with 3 elements.
-    #  It should contain a proxy URI, a proxy user name and a proxy password.
-    #  The proxy URI should be a String, an URI or nil.
-    #  The proxy user name and password should be a String.
-    #
-    #  If nil is given for the proxy URI, this option is just ignored.
-    #
-    #  If :proxy and :proxy_http_basic_authentication is specified, 
-    #  ArgumentError is raised.
-    #
-    # [:http_basic_authentication]
-    #  Synopsis:
-    #    :http_basic_authentication=>[user, password]
-    #
-    #  If :http_basic_authentication is specified,
-    #  the value should be an array which contains 2 strings:
-    #  username and password.
-    #  It is used for HTTP Basic authentication defined by RFC 2617.
-    #
-    # [:content_length_proc]
-    #  Synopsis:
-    #    :content_length_proc => lambda {|content_length| ... }
-    # 
-    #  If :content_length_proc option is specified, the option value procedure
-    #  is called before actual transfer is started.
-    #  It takes one argument which is expected content length in bytes.
-    # 
-    #  If two or more transfer is done by HTTP redirection, the procedure
-    #  is called only one for a last transfer.
-    # 
-    #  When expected content length is unknown, the procedure is called with
-    #  nil.
-    #  It is happen when HTTP response has no Content-Length header.
-    #
-    # [:progress_proc]
-    #  Synopsis:
-    #    :progress_proc => lambda {|size| ...}
-    #
-    #  If :progress_proc option is specified, the proc is called with one
-    #  argument each time when `open' gets content fragment from network.
-    #  The argument `size' `size' is a accumulated transfered size in bytes.
-    #
-    #  If two or more transfer is done by HTTP redirection, the procedure
-    #  is called only one for a last transfer.
-    #
-    #  :progress_proc and :content_length_proc are intended to be used for
-    #  progress bar.
-    #  For example, it can be implemented as follows using Ruby/ProgressBar.
-    #
-    #    pbar = nil
-    #    open("http://...",
-    #      :content_length_proc => lambda {|t|
-    #        if t && 0 < t
-    #          pbar = ProgressBar.new("...", t)
-    #          pbar.file_transfer_mode
-    #        end
-    #      },
-    #      :progress_proc => lambda {|s|
-    #        pbar.set s if pbar
-    #      }) {|f| ... }
-    #
-    # [:read_timeout]
-    #  Synopsis:
-    #    :read_timeout=>nil     (no timeout)
-    #    :read_timeout=>10      (10 second)
-    #
-    #  :read_timeout option specifies a timeout of read for http connections.
-    #
-    # [:ssl_ca_cert]
-    #  Synopsis:
-    #    :ssl_ca_cert=>filename
-    #
-    #  :ssl_ca_cert is used to specify CA certificate for SSL.
-    #  If it is given, default certificates are not used.
-    #
-    # [:ssl_verify_mode]
-    #  Synopsis:
-    #    :ssl_verify_mode=>mode
-    #
-    #  :ssl_verify_mode is used to specify openssl verify mode.
-    #
-    # OpenURI::OpenRead#open returns an IO like object if block is not given.
-    # Otherwise it yields the IO object and return the value of the block.
-    # The IO object is extended with OpenURI::Meta.
-    def open(*rest, &block)
-      OpenURI.open_uri(self, *rest, &block)
-    end
-
-    # OpenURI::OpenRead#read([options]) reads a content referenced by self and
-    # returns the content as string.
-    # The string is extended with OpenURI::Meta.
-    # The argument `options' is same as OpenURI::OpenRead#open.
-    def read(options={})
-      self.open(options) {|f|
-        str = f.read
-        Meta.init str, f
-        str
-      }
-    end
-  end
-end
-
-module URI
-  class Generic
-    # returns a proxy URI.
-    # The proxy URI is obtained from environment variables such as http_proxy,
-    # ftp_proxy, no_proxy, etc.
-    # If there is no proper proxy, nil is returned.
-    #
-    # Note that capitalized variables (HTTP_PROXY, FTP_PROXY, NO_PROXY, etc.)
-    # are examined too.
-    #
-    # But http_proxy and HTTP_PROXY is treated specially under CGI environment.
-    # It's because HTTP_PROXY may be set by Proxy: header.
-    # So HTTP_PROXY is not used.
-    # http_proxy is not used too if the variable is case insensitive.
-    # CGI_HTTP_PROXY can be used instead.
-    def find_proxy
-      name = self.scheme.downcase + '_proxy'
-      proxy_uri = nil
-      if name == 'http_proxy' && ENV.include?('REQUEST_METHOD') # CGI?
-        # HTTP_PROXY conflicts with *_proxy for proxy settings and
-        # HTTP_* for header information in CGI.
-        # So it should be careful to use it.
-        pairs = ENV.reject {|k, v| /\Ahttp_proxy\z/i !~ k }
-        case pairs.length
-        when 0 # no proxy setting anyway.
-          proxy_uri = nil
-        when 1
-          k, v = pairs.shift
-          if k == 'http_proxy' && ENV[k.upcase] == nil
-            # http_proxy is safe to use because ENV is case sensitive.
-            proxy_uri = ENV[name]
-          else
-            proxy_uri = nil
-          end
-        else # http_proxy is safe to use because ENV is case sensitive.
-          proxy_uri = ENV[name]
-        end
-        if !proxy_uri
-          # Use CGI_HTTP_PROXY.  cf. libwww-perl.
-          proxy_uri = ENV["CGI_#{name.upcase}"]
-        end
-      elsif name == 'http_proxy'
-        unless proxy_uri = ENV[name]
-          if proxy_uri = ENV[name.upcase]
-            warn 'The environment variable HTTP_PROXY is discouraged.  Use http_proxy.'
-          end
-        end
-      else
-        proxy_uri = ENV[name] || ENV[name.upcase]
-      end
-
-      if proxy_uri && self.host
-        require 'socket'
-        begin
-          addr = IPSocket.getaddress(self.host)
-          proxy_uri = nil if /\A127\.|\A::1\z/ =~ addr
-        rescue SocketError
-        end
-      end
-
-      if proxy_uri
-        proxy_uri = URI.parse(proxy_uri)
-        name = 'no_proxy'
-        if no_proxy = ENV[name] || ENV[name.upcase]
-          no_proxy.scan(/([^:,]*)(?::(\d+))?/) {|host, port|
-            if /(\A|\.)#{Regexp.quote host}\z/i =~ self.host &&
-               (!port || self.port == port.to_i)
-              proxy_uri = nil
-              break
-            end
-          }
-        end
-        proxy_uri
-      else
-        nil
-      end
-    end
-  end
-
-  class HTTP
-    def buffer_open(buf, proxy, options) # :nodoc:
-      OpenURI.open_http(buf, self, proxy, options)
-    end
-
-    include OpenURI::OpenRead
-  end
-
-  class FTP
-    def buffer_open(buf, proxy, options) # :nodoc:
-      if proxy
-        OpenURI.open_http(buf, self, proxy, options)
-        return
-      end
-      require 'net/ftp'
-
-      directories = self.path.split(%r{/}, -1)
-      directories.shift if directories[0] == '' # strip a field before leading slash
-      directories.each {|d|
-        d.gsub!(/%([0-9A-Fa-f][0-9A-Fa-f])/) { [$1].pack("H2") }
-      }
-      unless filename = directories.pop
-        raise ArgumentError, "no filename: #{self.inspect}"
-      end
-      directories.each {|d|
-        if /[\r\n]/ =~ d
-          raise ArgumentError, "invalid directory: #{d.inspect}"
-        end
-      }
-      if /[\r\n]/ =~ filename
-        raise ArgumentError, "invalid filename: #{filename.inspect}"
-      end
-      typecode = self.typecode
-      if typecode && /\A[aid]\z/ !~ typecode
-        raise ArgumentError, "invalid typecode: #{typecode.inspect}"
-      end
-
-      # The access sequence is defined by RFC 1738
-      ftp = Net::FTP.open(self.host)
-      # todo: extract user/passwd from .netrc.
-      user = 'anonymous'
-      passwd = nil
-      user, passwd = self.userinfo.split(/:/) if self.userinfo
-      ftp.login(user, passwd)
-      directories.each {|cwd|
-        ftp.voidcmd("CWD #{cwd}")
-      }
-      if typecode
-        # xxx: typecode D is not handled.
-        ftp.voidcmd("TYPE #{typecode.upcase}")
-      end
-      if options[:content_length_proc]
-        options[:content_length_proc].call(ftp.size(filename))
-      end
-      ftp.retrbinary("RETR #{filename}", 4096) { |str|
-        buf << str
-        options[:progress_proc].call(buf.size) if options[:progress_proc]
-      }
-      ftp.close
-      buf.io.rewind
-    end
-
-    include OpenURI::OpenRead
-  end
-end
-# :startdoc:

Modified: MacRuby/branches/testing/lib/singleton.rb
===================================================================
--- MacRuby/branches/testing/lib/singleton.rb	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/lib/singleton.rb	2008-06-05 08:33:02 UTC (rev 249)
@@ -85,6 +85,10 @@
       Singleton.__init__(super)
     end
 
+    def _load(str)
+      instance
+    end
+
     private
     
     #  ensure that the Singleton pattern is properly inherited   
@@ -92,10 +96,6 @@
       super
       Singleton.__init__(sub_klass)
     end
-    
-    def _load(str) 
-      instance 
-    end
   end
 
   class << Singleton

Modified: MacRuby/branches/testing/lib/un.rb
===================================================================
--- MacRuby/branches/testing/lib/un.rb	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/lib/un.rb	2008-06-05 08:33:02 UTC (rev 249)
@@ -214,6 +214,33 @@
 end
 
 ##
+# Wait until the file becomes writable.
+#
+#   ruby -run -e wait_writable -- [OPTION] FILE
+#
+
+def wait_writable
+  setup("n:w:v") do |argv, options|
+    verbose = options[:verbose]
+    n = options[:n] and n = Integer(n)
+    wait = (wait = options[:w]) ? Float(wait) : 0.2
+    argv.each do |file|
+      begin
+        open(file, "r+b")
+      rescue Errno::ENOENT
+        break
+      rescue Errno::EACCES => e
+        raise if n and (n -= 1) <= 0
+        puts e
+        STDOUT.flush
+        sleep wait
+        retry
+      end
+    end
+  end
+end
+
+##
 # Display help message.
 #
 #   ruby -run -e help [COMMAND]

Modified: MacRuby/branches/testing/lib/webrick/httpservlet/abstract.rb
===================================================================
--- MacRuby/branches/testing/lib/webrick/httpservlet/abstract.rb	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/lib/webrick/httpservlet/abstract.rb	2008-06-05 08:33:02 UTC (rev 249)
@@ -58,7 +58,7 @@
 
       def redirect_to_directory_uri(req, res)
         if req.path[-1] != ?/
-          location = req.path + "/"
+          location = WEBrick::HTTPUtils.escape_path(req.path + "/")
           if req.query_string && req.query_string.size > 0
             location << "?" << req.query_string
           end

Modified: MacRuby/branches/testing/lib/webrick/httpservlet/cgi_runner.rb
===================================================================
--- MacRuby/branches/testing/lib/webrick/httpservlet/cgi_runner.rb	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/lib/webrick/httpservlet/cgi_runner.rb	2008-06-05 08:33:02 UTC (rev 249)
@@ -39,7 +39,9 @@
 Dir::chdir dir
 
 if interpreter = ARGV[0]
-  exec(interpreter, ENV["SCRIPT_FILENAME"])
+  argv = ARGV.dup
+  argv << ENV["SCRIPT_FILENAME"]
+  exec(*argv)
   # NOTREACHED
 end
 exec ENV["SCRIPT_FILENAME"]

Modified: MacRuby/branches/testing/lib/webrick/httpservlet/cgihandler.rb
===================================================================
--- MacRuby/branches/testing/lib/webrick/httpservlet/cgihandler.rb	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/lib/webrick/httpservlet/cgihandler.rb	2008-06-05 08:33:02 UTC (rev 249)
@@ -87,6 +87,10 @@
             res.status = $1.to_i
             header.delete('status')
           end
+          if header.has_key?('location')
+            # RFC 3875 6.2.3, 6.2.4
+            res.status = 302 unless (300...400) === res.status
+          end
           if header.has_key?('set-cookie')
             header['set-cookie'].each{|k|
               res.cookies << Cookie.parse_set_cookie(k)

Modified: MacRuby/branches/testing/lib/webrick/httpservlet/filehandler.rb
===================================================================
--- MacRuby/branches/testing/lib/webrick/httpservlet/filehandler.rb	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/lib/webrick/httpservlet/filehandler.rb	2008-06-05 08:33:02 UTC (rev 249)
@@ -199,26 +199,38 @@
 
       private
 
+      def trailing_pathsep?(path)
+        # check for trailing path separator:
+        #   File.dirname("/aaaa/bbbb/")      #=> "/aaaa")
+        #   File.dirname("/aaaa/bbbb/x")     #=> "/aaaa/bbbb")
+        #   File.dirname("/aaaa/bbbb")       #=> "/aaaa")
+        #   File.dirname("/aaaa/bbbbx")      #=> "/aaaa")
+        return File.dirname(path) != File.dirname(path+"x")
+      end
+
       def prevent_directory_traversal(req, res)
-        # Preventing directory traversal on DOSISH platforms;
+        # Preventing directory traversal on Windows platforms;
         # Backslashes (0x5c) in path_info are not interpreted as special
         # character in URI notation. So the value of path_info should be
         # normalize before accessing to the filesystem.
-        if File::ALT_SEPARATOR
+
+        if trailing_pathsep?(req.path_info)
           # File.expand_path removes the trailing path separator.
           # Adding a character is a workaround to save it.
           #  File.expand_path("/aaa/")        #=> "/aaa"
           #  File.expand_path("/aaa/" + "x")  #=> "/aaa/x"
           expanded = File.expand_path(req.path_info + "x")
-          expanded[-1, 1] = ""  # remove trailing "x"
-          req.path_info = expanded
+          expanded.chop!  # remove trailing "x"
+        else
+          expanded = File.expand_path(req.path_info)
         end
+        req.path_info = expanded
       end
 
       def exec_handler(req, res)
         raise HTTPStatus::NotFound, "`#{req.path}' not found" unless @root
         if set_filename(req, res)
-          handler = get_handler(req)
+          handler = get_handler(req, res)
           call_callback(:HandlerCallback, req, res)
           h = handler.get_instance(@config, res.filename)
           h.service(req, res)
@@ -228,9 +240,13 @@
         return false
       end
 
-      def get_handler(req)
-        suffix1 = (/\.(\w+)$/ =~ req.script_name) && $1.downcase
-        suffix2 = (/\.(\w+)\.[\w\-]+$/ =~ req.script_name) && $1.downcase
+      def get_handler(req, res)
+        suffix1 = (/\.(\w+)\z/ =~ res.filename) && $1.downcase
+        if /\.(\w+)\.([\w\-]+)\z/ =~ res.filename
+          if @options[:AcceptableLanguages].include?($2.downcase)
+            suffix2 = $1.downcase
+          end
+        end
         handler_table = @options[:HandlerTable]
         return handler_table[suffix1] || handler_table[suffix2] ||
                HandlerTable[suffix1] || HandlerTable[suffix2] ||
@@ -243,15 +259,13 @@
 
         path_info.unshift("")  # dummy for checking @root dir
         while base = path_info.first
-          check_filename(req, res, base)
           break if base == "/"
-          break unless File.directory?(res.filename + base)
+          break unless File.directory?(File.expand_path(res.filename + base))
           shift_path_info(req, res, path_info)
           call_callback(:DirectoryCallback, req, res)
         end
 
         if base = path_info.first
-          check_filename(req, res, base)
           if base == "/"
             if file = search_index_file(req, res)
               shift_path_info(req, res, path_info, file)
@@ -272,12 +286,10 @@
       end
 
       def check_filename(req, res, name)
-        @options[:NondisclosureName].each{|pattern|
-          if File.fnmatch("/#{pattern}", name, File::FNM_CASEFOLD)
-            @logger.warn("the request refers nondisclosure name `#{name}'.")
-            raise HTTPStatus::NotFound, "`#{req.path}' not found."
-          end
-        }
+        if nondisclosure_name?(name) || windows_ambiguous_name?(name)
+          @logger.warn("the request refers nondisclosure name `#{name}'.")
+          raise HTTPStatus::NotFound, "`#{req.path}' not found."
+        end
       end
 
       def shift_path_info(req, res, path_info, base=nil)
@@ -285,7 +297,8 @@
         base = base || tmp
         req.path_info = path_info.join
         req.script_name << base
-        res.filename << base
+        res.filename = File.expand_path(res.filename + base)
+        check_filename(req, res, File.basename(res.filename))
       end
 
       def search_index_file(req, res)
@@ -325,6 +338,12 @@
         end
       end
 
+      def windows_ambiguous_name?(name)
+        return true if /[. ]+\z/ =~ name
+        return true if /::\$DATA\z/ =~ name
+        return false
+      end
+
       def nondisclosure_name?(name)
         @options[:NondisclosureName].each{|pattern|
           if File.fnmatch(pattern, name, File::FNM_CASEFOLD)
@@ -343,7 +362,8 @@
         list = Dir::entries(local_path).collect{|name|
           next if name == "." || name == ".."
           next if nondisclosure_name?(name)
-          st = (File::stat(local_path + name) rescue nil)
+          next if windows_ambiguous_name?(name)
+          st = (File::stat(File.join(local_path, name)) rescue nil)
           if st.nil?
             [ name, nil, -1 ]
           elsif st.directory?
@@ -383,7 +403,7 @@
         res.body << "<A HREF=\"?S=#{d1}\">Size</A>\n"
         res.body << "<HR>\n"
        
-        list.unshift [ "..", File::mtime(local_path+".."), -1 ]
+        list.unshift [ "..", File::mtime(local_path+"/.."), -1 ]
         list.each{ |name, time, size|
           if name == ".."
             dname = "Parent Directory"

Modified: MacRuby/branches/testing/load.c
===================================================================
--- MacRuby/branches/testing/load.c	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/load.c	2008-06-05 08:33:02 UTC (rev 249)
@@ -407,7 +407,7 @@
     return rb_require_safe(fname, rb_safe_level());
 }
 
-static int
+/*static*/ int
 search_required(VALUE fname, volatile VALUE *path)
 {
     VALUE tmp;
@@ -650,7 +650,7 @@
 static VALUE
 rb_f_autoload(VALUE obj, VALUE sym, VALUE file)
 {
-    VALUE klass = ruby_cbase();
+    VALUE klass = rb_vm_cbase();
     if (NIL_P(klass)) {
 	rb_raise(rb_eTypeError, "Can not set autoload on singleton class");
     }
@@ -664,8 +664,8 @@
 static VALUE
 rb_f_autoload_p(VALUE obj, VALUE sym)
 {
-    /* use ruby_cbase() as same as rb_f_autoload. */
-    VALUE klass = ruby_cbase();
+    /* use rb_vm_cbase() as same as rb_f_autoload. */
+    VALUE klass = rb_vm_cbase();
     if (NIL_P(klass)) {
 	return Qnil;
     }
@@ -686,7 +686,7 @@
 
     rb_define_virtual_variable("$\"", get_loaded_features, 0);
     rb_define_virtual_variable("$LOADED_FEATURES", get_loaded_features, 0);
-    GC_WB(&GET_VM()->loaded_features, rb_ary_new());
+    GC_WB(&vm->loaded_features, rb_ary_new());
 
     rb_define_global_function("load", rb_f_load, -1);
     rb_define_global_function("require", rb_f_require, 1);

Modified: MacRuby/branches/testing/main.c
===================================================================
--- MacRuby/branches/testing/main.c	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/main.c	2008-06-05 08:33:02 UTC (rev 249)
@@ -2,7 +2,7 @@
 
   main.c -
 
-  $Author: akr $
+  $Author: nobu $
   created at: Fri Aug 19 13:19:58 JST 1994
 
   Copyright (C) 1993-2007 Yukihiro Matsumoto
@@ -10,7 +10,7 @@
 **********************************************************************/
 
 #undef RUBY_EXPORT
-#include "ruby/ruby.h"
+#include "ruby.h"
 #ifdef HAVE_LOCALE_H
 #include <locale.h>
 #endif
@@ -21,7 +21,6 @@
 main(int argc, char **argv, char **envp)
 {
 #ifdef RUBY_DEBUG_ENV
-    extern void ruby_set_debug_option(const char *);
     ruby_set_debug_option(getenv("RUBY_DEBUG"));
 #endif
 #ifdef HAVE_LOCALE_H

Copied: MacRuby/branches/testing/markgc.c (from rev 248, MacRuby/trunk/markgc.c)
===================================================================
--- MacRuby/branches/testing/markgc.c	                        (rev 0)
+++ MacRuby/branches/testing/markgc.c	2008-06-05 08:33:02 UTC (rev 249)
@@ -0,0 +1,451 @@
+/*
+ * Copyright (c) 2007 Apple Inc.  All Rights Reserved.
+ * 
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#import <stdio.h>
+#include <fcntl.h>
+#import <sys/stat.h>
+#import <mach-o/fat.h>
+#import <mach-o/arch.h>
+#import <mach-o/loader.h>
+
+typedef char bool;
+#define true 1
+#define false 0
+
+bool debug;
+bool verbose;
+bool quiet;
+bool rrOnly;
+bool patch = true;
+
+struct gcinfo {
+        bool hasObjC;
+        bool hasInfo;
+        uint32_t flags;
+        char *arch;
+} GCInfo[4];
+
+void dumpinfo(char *filename);
+
+int Errors = 0;
+char *FileBase;
+size_t FileSize;
+const char *FileName;
+
+int main(int argc, char *argv[]) {
+    //NSAutoreleasePool *pool = [NSAutoreleasePool new];
+    int i;
+    //dumpinfo("/System/Library/Frameworks/AppKit.framework/AppKit");
+    if (argc == 1) {
+        printf("Usage: gcinfo [-v] [-r] [--] library_or_executable_image [image2 ...]\n");
+        printf(" prints Garbage Collection readiness of named images, ignoring those without ObjC segments\n");
+        printf("  'GC'      - compiled with write-barriers, presumably otherwise aware\n");
+        printf("  'RR'      - retain/release (presumed) aware for non-GC\n");
+        printf("  'GC-only' - compiled with write-barriers and marked at compile time as not being retain/release savvy\n");
+        printf("  -v        - provide archtectural details\n");
+        printf("  -r        - only show libraries that are non-GC, e.g. RR only\n");
+        printf("  --        - read files & directories from stdin, e.g. find /Plug-ins | gcinfo --\n");
+        printf("\nAuthor: blaine at apple.com\n");
+        exit(0);
+    }
+    for (i = 1; i < argc; ++i) {
+        if (!strcmp(argv[i], "-v")) {
+            verbose = true;
+            continue;
+        }
+        if (!strcmp(argv[i], "-d")) {
+            debug = true;
+            continue;
+        }
+        if (!strcmp(argv[i], "-q")) {
+            quiet = true;
+            continue;
+        }
+        if (!strcmp(argv[i], "-r")) {
+            quiet = true;
+            rrOnly = true;
+            continue;
+        }
+        if (!strcmp(argv[i], "-p")) {
+            patch = true;
+            continue;
+        }
+        if (!strcmp(argv[i], "--")) {
+            char buf[1024];
+            while (fgets(buf, 1024, stdin)) {
+                int len = strlen(buf);
+                buf[len-1] = 0;
+                dumpinfo(buf);
+            }
+            continue;
+        }
+        dumpinfo(argv[i]);
+    }
+    return Errors;
+}
+
+struct imageInfo {
+    uint32_t version;
+    uint32_t flags;
+};
+
+void patchFile(uint32_t value, size_t offset) {
+    int fd = open(FileName, 1);
+    off_t lresult = lseek(fd, offset, SEEK_SET);
+    if (lresult == -1) {
+        printf("couldn't seek to %x position on fd %d\n", offset, fd);
+        ++Errors;
+        return;
+    }
+    int wresult = write(fd, &value, 4);
+    if (wresult != 4) {
+        ++Errors;
+        printf("didn't write new value\n");
+    }
+    else {
+        printf("patched %s at offset %p\n", FileName, offset);
+    }
+    close(fd);
+}
+
+uint32_t iiflags(struct imageInfo *ii, uint32_t size, bool needsFlip) {
+    if (needsFlip) {
+        ii->flags = OSSwapInt32(ii->flags);
+    }
+    if (debug) printf("flags->%x, nitems %d\n", ii->flags, size/sizeof(struct imageInfo));
+    uint32_t flags = ii->flags;
+    if (patch && (flags&0x2)==0) {
+        //printf("will patch %s at offset %p\n", FileName, (char*)(&ii->flags) - FileBase);
+        uint32_t newvalue = flags | 0x2;
+        if (needsFlip) newvalue = OSSwapInt32(newvalue);
+        patchFile(newvalue, (char*)(&ii->flags) - FileBase);
+    }
+    for(int niis = 1; niis < size/sizeof(struct imageInfo); ++niis) {
+        if (needsFlip) ii[niis].flags = OSSwapInt32(ii[niis].flags);
+        if (ii[niis].flags != flags) {
+            // uh, oh.
+            printf("XXX ii[%d].flags %x != ii[0].flags %x\n", niis, ii[niis].flags, flags);
+            ++Errors;
+        }
+    }
+    return flags;
+}
+
+void printflags(uint32_t flags) {
+    if (flags & 0x1) printf(" F&C");
+    if (flags & 0x2) printf(" GC");
+    if (flags & 0x4) printf(" GC-only");
+    else printf(" RR");
+}
+
+/*
+void doimageinfo(struct imageInfo *ii, uint32_t size, bool needsFlip) {
+    uint32_t flags = iiflags(ii, size, needsFlip);
+    printflags(flags);
+}
+*/
+
+
+void dosect32(void *start, struct section *sect, bool needsFlip, struct gcinfo *gcip) {
+    if (debug) printf("section %s from segment %s\n", sect->sectname, sect->segname);
+    if (strcmp(sect->segname, "__OBJC")) return;
+    gcip->hasObjC = true;
+    if (strcmp(sect->sectname, "__image_info")) return;
+    gcip->hasInfo = true;
+    if (needsFlip) {
+        sect->offset = OSSwapInt32(sect->offset);
+        sect->size = OSSwapInt32(sect->size);
+    }
+    // these guys aren't inline - they point elsewhere
+    gcip->flags = iiflags(start + sect->offset, sect->size, needsFlip);
+}
+
+void dosect64(void *start, struct section_64 *sect, bool needsFlip, struct gcinfo *gcip) {
+    if (debug) printf("section %s from segment %s\n", sect->sectname, sect->segname);
+    if (strcmp(sect->segname, "__OBJC") && strcmp(sect->segname, "__DATA")) return;
+    if (strcmp(sect->sectname, "__image_info") && strncmp(sect->sectname, "__objc_imageinfo", 16)) return;
+    gcip->hasObjC = true;
+    gcip->hasInfo = true;
+    if (needsFlip) {
+        sect->offset = OSSwapInt32(sect->offset);
+        sect->size = OSSwapInt64(sect->size);
+    }
+    // these guys aren't inline - they point elsewhere
+    gcip->flags = iiflags(start + sect->offset, sect->size, needsFlip);
+}
+
+void doseg32(void *start, struct segment_command *seg, bool needsFlip, struct gcinfo *gcip) {
+    // lets do sections
+    if (needsFlip) {
+        seg->fileoff = OSSwapInt32(seg->fileoff);
+        seg->nsects = OSSwapInt32(seg->nsects);
+    }
+    if (debug) printf("segment name: %s, nsects %d\n", seg->segname, seg->nsects);
+    if (seg->segname[0]) {
+        if (strcmp("__OBJC", seg->segname)) return;
+    }
+    int nsects;
+    struct section *sect = (struct section *)(seg + 1);
+    for (int nsects = 0; nsects < seg->nsects; ++nsects) {
+        // sections directly follow
+        
+        dosect32(start, sect + nsects, needsFlip, gcip);
+    }
+}
+void doseg64(void *start, struct segment_command_64 *seg, bool needsFlip, struct gcinfo *gcip) {
+    if (debug) printf("segment name: %s\n", seg->segname);
+    if (seg->segname[0] && strcmp("__OBJC", seg->segname) && strcmp("__DATA", seg->segname)) return;
+    gcip->hasObjC = true;
+    // lets do sections
+    if (needsFlip) {
+        seg->fileoff = OSSwapInt64(seg->fileoff);
+        seg->nsects = OSSwapInt32(seg->nsects);
+    }
+    int nsects;
+    struct section_64 *sect = (struct section_64 *)(seg + 1);
+    for (int nsects = 0; nsects < seg->nsects; ++nsects) {
+        // sections directly follow
+        
+        dosect64(start, sect + nsects, needsFlip, gcip);
+    }
+}
+
+#if 0
+/*
+ * A variable length string in a load command is represented by an lc_str
+ * union.  The strings are stored just after the load command structure and
+ * the offset is from the start of the load command structure.  The size
+ * of the string is reflected in the cmdsize field of the load command.
+ * Once again any padded bytes to bring the cmdsize field to a multiple
+ * of 4 bytes must be zero.
+ */
+union lc_str {
+	uint32_t	offset;	/* offset to the string */
+#ifndef __LP64__
+	char		*ptr;	/* pointer to the string */
+#endif 
+};
+
+struct dylib {
+    union lc_str  name;			/* library's path name */
+    uint32_t timestamp;			/* library's build time stamp */
+    uint32_t current_version;		/* library's current version number */
+    uint32_t compatibility_version;	/* library's compatibility vers number*/
+};
+
+ * A dynamically linked shared library (filetype == MH_DYLIB in the mach header)
+ * contains a dylib_command (cmd == LC_ID_DYLIB) to identify the library.
+ * An object that uses a dynamically linked shared library also contains a
+ * dylib_command (cmd == LC_LOAD_DYLIB, LC_LOAD_WEAK_DYLIB, or
+ * LC_REEXPORT_DYLIB) for each library it uses.
+
+struct dylib_command {
+	uint32_t	cmd;		/* LC_ID_DYLIB, LC_LOAD_{,WEAK_}DYLIB,
+					   LC_REEXPORT_DYLIB */
+	uint32_t	cmdsize;	/* includes pathname string */
+	struct dylib	dylib;		/* the library identification */
+};
+#endif
+
+void dodylib(void *start, struct dylib_command *dylibCmd, bool needsFlip) {
+    if (!verbose) return;
+    if (needsFlip) {
+    }
+    int count = dylibCmd->cmdsize - sizeof(struct dylib_command);
+    //printf("offset is %d, count is %d\n", dylibCmd->dylib.name.offset, count);
+    if (dylibCmd->dylib.name.offset > count) return;
+    //printf("-->%.*s<---", count, ((void *)dylibCmd)+dylibCmd->dylib.name.offset);
+    if (verbose) printf("load %s\n", ((void *)dylibCmd)+dylibCmd->dylib.name.offset);
+}
+
+struct load_command *doloadcommand(void *start, struct load_command *lc, bool needsFlip, bool is32, struct gcinfo *gcip) {
+    if (needsFlip) {
+        lc->cmd = OSSwapInt32(lc->cmd);
+        lc->cmdsize = OSSwapInt32(lc->cmdsize);
+    }
+
+    switch(lc->cmd) {
+    case LC_SEGMENT_64:
+	if (debug) printf("...segment64\n");
+        if (is32) printf("XXX we have a 64-bit segment in a 32-bit mach-o\n");
+        doseg64(start, (struct segment_command_64 *)lc, needsFlip, gcip);
+        break;
+    case LC_SEGMENT:
+	if (debug) printf("...segment32\n");
+        doseg32(start, (struct segment_command *)lc, needsFlip, gcip);
+        break;
+    case LC_SYMTAB: if (debug) printf("...dynamic symtab\n"); break;
+    case LC_DYSYMTAB: if (debug) printf("...symtab\n"); break;
+    case LC_LOAD_DYLIB:
+        dodylib(start, (struct dylib_command *)lc, needsFlip);
+        break;
+    case LC_SUB_UMBRELLA: if (debug) printf("...load subumbrella\n"); break;
+    default:    if (debug) printf("cmd is %x\n", lc->cmd); break;
+    }
+    
+    return (struct load_command *)((void *)lc + lc->cmdsize);
+}
+
+void doofile(void *start, uint32_t size, struct gcinfo *gcip) {
+    struct mach_header *mh = (struct mach_header *)start;
+    bool isFlipped = false;
+    if (mh->magic == MH_CIGAM || mh->magic == MH_CIGAM_64) {
+        if (debug) printf("(flipping)\n");
+        mh->magic = OSSwapInt32(mh->magic);
+        mh->cputype = OSSwapInt32(mh->cputype);
+        mh->cpusubtype = OSSwapInt32(mh->cpusubtype);
+        mh->filetype = OSSwapInt32(mh->filetype);
+        mh->ncmds = OSSwapInt32(mh->ncmds);
+        mh->sizeofcmds = OSSwapInt32(mh->sizeofcmds);
+        mh->flags = OSSwapInt32(mh->flags);
+        isFlipped = true;
+    }
+    if (rrOnly && mh->filetype != 6) return; // ignore executables
+    NXArchInfo *info = (NXArchInfo *)NXGetArchInfoFromCpuType(mh->cputype, mh->cpusubtype);
+    //printf("%s:", info->description);
+    gcip->arch = (char *)info->description;
+    //if (debug) printf("...description is %s\n", info->description);
+    bool is32 = (mh->cputype == 18 || mh->cputype == 7);
+    if (debug) printf("is 32? %d\n", is32);
+    if (debug) printf("filetype -> %d\n", mh->filetype);
+    if (debug) printf("ncmds -> %d\n", mh->ncmds);
+    struct load_command *lc = (is32 ? (struct load_command *)(mh + 1) : (struct load_command *)((struct mach_header_64 *)start + 1));
+    int ncmds;
+    for (ncmds = 0; ncmds < mh->ncmds; ++ncmds) {
+        lc = doloadcommand(start, lc, isFlipped, is32, gcip);
+    }
+    //printf("\n");
+}
+
+void initGCInfo() {
+    bzero((void *)GCInfo, sizeof(GCInfo));
+}
+
+void printGCInfo(char *filename) {
+    if (!GCInfo[0].hasObjC) return; // don't bother
+    // verify that flags are all the same
+    uint32_t flags = GCInfo[0].flags;
+    bool allSame = true;
+    for (int i = 1; i < 4 && GCInfo[i].arch; ++i) {
+        if (flags != GCInfo[i].flags) {
+            allSame = false;
+        }
+    }
+    if (rrOnly) {
+        if (allSame && (flags & 0x2))
+            return;
+        printf("*** not all GC in %s:\n", filename);
+    }
+    if (allSame && !verbose) {
+        printf("%s:", filename);
+        printflags(flags);
+        printf("\n");
+    }
+    else {
+        printf("%s:\n", filename);
+        for (int i = 0; i < 4 && GCInfo[i].arch; ++i) {
+            printf("%s:", GCInfo[i].arch);
+            printflags(GCInfo[i].flags);
+            printf("\n");
+        }
+        printf("\n");
+    }
+}
+
+void dofat(void *start) {
+    struct fat_header *fh = start;
+    bool needsFlip = false;
+    if (fh->magic == FAT_CIGAM) {
+        fh->nfat_arch = OSSwapInt32(fh->nfat_arch);
+        needsFlip = true;
+    }
+    if (debug) printf("%d architectures\n", fh->nfat_arch);
+    int narchs;
+    struct fat_arch *arch_ptr = (struct fat_arch *)(fh + 1);
+    for (narchs = 0; narchs < fh->nfat_arch; ++narchs) {
+        if (needsFlip) {
+            arch_ptr->offset = OSSwapInt32(arch_ptr->offset);
+            arch_ptr->size = OSSwapInt32(arch_ptr->size);
+        }
+        doofile(start+arch_ptr->offset, arch_ptr->size, &GCInfo[narchs]);
+        arch_ptr++;
+    }
+}
+
+bool openFile(const char *filename) {
+    FileName = filename;
+    // get size
+    struct stat statb;
+    int fd = open(filename, 0);
+    if (fd < 0) {
+        printf("couldn't open %s for reading\n", filename);
+        return false;
+    }
+    int osresult = fstat(fd, &statb);
+    if (osresult != 0) {
+        printf("couldn't get size of %s\n", filename);
+        close(fd);
+        return false;
+    }
+    FileSize = statb.st_size;
+    FileBase = malloc(FileSize);
+    if (!FileBase) {
+        printf("couldn't malloc %d bytes\n", FileSize);
+        close(fd);
+        return false;
+    }
+    off_t readsize = read(fd, FileBase, FileSize);
+    if (readsize != FileSize) {
+        printf("read %d bytes, wanted %d\n", readsize, FileSize);
+        close(fd);
+        return false;
+    }
+    close(fd);
+    return true;
+}
+
+void closeFile() {
+    free(FileBase);
+}
+
+void dumpinfo(char *filename) {
+    initGCInfo();
+    openFile(filename);
+    struct fat_header *fh = (struct fat_header *)FileBase;
+    if (fh->magic == FAT_MAGIC || fh->magic == FAT_CIGAM) {
+        dofat((void *)FileBase);
+        //printGCInfo(filename);
+    }
+    else if (fh->magic == MH_MAGIC || fh->magic == MH_CIGAM || fh->magic == MH_MAGIC_64 || fh->magic == MH_CIGAM_64) {
+        doofile((void *)FileBase, FileSize, &GCInfo[0]);
+        //printGCInfo(filename);
+    }
+    else if (!quiet) {
+        printf("don't understand %s!\n", filename);
+    }
+    closeFile();
+ }
+

Modified: MacRuby/branches/testing/marshal.c
===================================================================
--- MacRuby/branches/testing/marshal.c	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/marshal.c	2008-06-05 08:33:02 UTC (rev 249)
@@ -2,7 +2,7 @@
 
   marshal.c -
 
-  $Author: matz $
+  $Author: mame $
   created at: Thu Apr 27 16:30:01 JST 1995
 
   Copyright (C) 1993-2007 Yukihiro Matsumoto
@@ -97,7 +97,9 @@
 static int
 mark_marshal_compat_i(st_data_t key, st_data_t value)
 {
+#if !WITH_OBJC
     marshal_compat_t *p = (marshal_compat_t *)value;
+#endif
     rb_gc_mark(p->newclass);
     rb_gc_mark(p->oldclass);
     return ST_CONTINUE;
@@ -149,11 +151,21 @@
 };
 
 static void
+check_dump_arg(struct dump_arg *arg)
+{
+    if (!DATA_PTR(arg->wrapper)) {
+	rb_raise(rb_eRuntimeError, "Marshal.dump reentered");
+    }
+}
+
+static void
 mark_dump_arg(void *ptr)
 {
+#if !WITH_OBJC
     struct dump_arg *p = ptr;
     if (!ptr)
         return;
+#endif
     rb_mark_set(p->data);
     rb_mark_hash(p->compat_tbl);
 }
@@ -406,7 +418,7 @@
 static void
 w_extended(VALUE klass, struct dump_arg *arg, int check)
 {
-    char *path;
+    const char *path;
 
     if (check && FL_TEST(klass, FL_SINGLETON)) {
 	if (RCLASS_M_TBL(klass)->num_entries ||
@@ -598,23 +610,25 @@
     else {
 	if (OBJ_TAINTED(obj)) arg->taint = Qtrue;
 
-	if (rb_respond_to(obj, s_mdump)) {
+	if (rb_obj_respond_to(obj, s_mdump, Qtrue)) {
 	    volatile VALUE v;
 
             st_add_direct(arg->data, obj, arg->data->num_entries);
 
 	    v = rb_funcall(obj, s_mdump, 0, 0);
+	    check_dump_arg(arg);
 	    w_class(TYPE_USRMARSHAL, obj, arg, Qfalse);
 	    w_object(v, arg, limit);
 	    if (hasiv) w_ivar(obj, 0, &c_arg);
 	    return;
 	}
-	if (rb_respond_to(obj, s_dump)) {
+	if (rb_obj_respond_to(obj, s_dump, Qtrue)) {
 	    VALUE v;
             st_table *ivtbl2 = 0;
             int hasiv2;
 
 	    v = rb_funcall(obj, s_dump, 1, INT2NUM(limit));
+	    check_dump_arg(arg);
 	    if (TYPE(v) != T_STRING) {
 		rb_raise(rb_eTypeError, "_dump() must return string");
 	    }
@@ -801,12 +815,13 @@
 	    {
 		VALUE v;
 
-		if (!rb_respond_to(obj, s_dump_data)) {
+		if (!rb_obj_respond_to(obj, s_dump_data, Qtrue)) {
 		    rb_raise(rb_eTypeError,
 			     "no marshal_dump is defined for class %s",
 			     rb_obj_classname(obj));
 		}
 		v = rb_funcall(obj, s_dump_data, 0);
+		check_dump_arg(arg);
 		w_class(TYPE_DATA, obj, arg, Qtrue);
 		w_object(v, arg, limit);
 	    }
@@ -837,6 +852,7 @@
 static VALUE
 dump_ensure(struct dump_arg *arg)
 {
+    if (!DATA_PTR(arg->wrapper)) return 0;
     st_free_table(arg->symbols);
     st_free_table(arg->data);
     st_free_table(arg->compat_tbl);
@@ -896,13 +912,13 @@
     }
     arg.dest = 0;
     if (!NIL_P(port)) {
-	if (!rb_respond_to(port, s_write)) {
+	if (!rb_obj_respond_to(port, s_write, Qtrue)) {
 	  type_error:
 	    rb_raise(rb_eTypeError, "instance of IO needed");
 	}
 	arg.str = rb_str_buf_new(0);
 	arg.dest = port;
-	if (rb_respond_to(port, s_binmode)) {
+	if (rb_obj_respond_to(port, s_binmode, Qtrue)) {
 	    rb_funcall2(port, s_binmode, 0, 0);
 	}
     }
@@ -942,6 +958,14 @@
     VALUE compat_tbl_wrapper;
 };
 
+static void
+check_load_arg(struct load_arg *arg)
+{
+    if (!DATA_PTR(arg->compat_tbl_wrapper)) {
+	rb_raise(rb_eRuntimeError, "Marshal.load reentered");
+    }
+}
+
 static VALUE r_entry(VALUE v, struct load_arg *arg);
 static VALUE r_object(struct load_arg *arg);
 static VALUE path2class(const char *path);
@@ -962,6 +986,7 @@
     else {
 	VALUE src = arg->src;
 	VALUE v = rb_funcall2(src, s_getbyte, 0, 0);
+	check_load_arg(arg);
 	if (NIL_P(v)) rb_eof_error();
 	c = (unsigned char)NUM2CHR(v);
     }
@@ -971,7 +996,7 @@
 static void
 long_toobig(int size)
 {
-    rb_raise(rb_eTypeError, "long too big for this architecture (size %d, given %d)",
+    rb_raise(rb_eTypeError, "long too big for this architecture (size %zd, given %d)",
 	     sizeof(long), size);
 }
 
@@ -1038,6 +1063,7 @@
 	VALUE src = arg->src;
 	VALUE n = LONG2NUM(len);
 	str = rb_funcall2(src, s_read, 1, &n);
+	check_load_arg(arg);
 	if (NIL_P(str)) goto too_short;
 	StringValue(str);
 	if (RSTRING_CLEN(str) != len) goto too_short;
@@ -1132,6 +1158,7 @@
     }
     if (arg->proc) {
 	v = rb_funcall(arg->proc, rb_intern("call"), 1, v);
+	check_load_arg(arg);
     }
     return v;
 }
@@ -1214,11 +1241,13 @@
       case TYPE_LINK:
 	id = r_long(arg);
 	v = rb_hash_aref(arg->data, LONG2FIX(id));
+	check_load_arg(arg);
 	if (NIL_P(v)) {
 	    rb_raise(rb_eArgError, "dump format error (unlinked)");
 	}
 	if (arg->proc) {
 	    v = rb_funcall(arg->proc, rb_intern("call"), 1, v);
+	    check_load_arg(arg);
 	}
 	break;
 
@@ -1249,7 +1278,6 @@
       case TYPE_UCLASS:
 	{
 	    VALUE c = path2class(r_unique(arg));
-	    bool non_native;
 
 	    if (FL_TEST(c, FL_SINGLETON)) {
 		rb_raise(rb_eTypeError, "singleton can't be loaded");
@@ -1463,7 +1491,7 @@
 	    VALUE klass = path2class(r_unique(arg));
 	    VALUE data;
 
-	    if (!rb_respond_to(klass, s_load)) {
+	    if (!rb_obj_respond_to(klass, s_load, Qtrue)) {
 		rb_raise(rb_eTypeError, "class %s needs to have method `_load'",
 			 rb_class2name(klass));
 	    }
@@ -1473,6 +1501,7 @@
 		*ivp = Qfalse;
 	    }
 	    v = rb_funcall(klass, s_load, 1, data);
+	    check_load_arg(arg);
 	    v = r_entry(v, arg);
             v = r_leave(v, arg);
 	}
@@ -1490,13 +1519,14 @@
                     rb_extend_object(v, m);
                 }
             }
-	    if (!rb_respond_to(v, s_mload)) {
+	    if (!rb_obj_respond_to(v, s_mload, Qtrue)) {
 		rb_raise(rb_eTypeError, "instance of %s needs to have method `marshal_load'",
 			 rb_class2name(klass));
 	    }
 	    v = r_entry(v, arg);
 	    data = r_object(arg);
 	    rb_funcall(v, s_mload, 1, data);
+	    check_load_arg(arg);
             v = r_leave(v, arg);
 	}
         break;
@@ -1516,13 +1546,14 @@
       case TYPE_DATA:
        {
            VALUE klass = path2class(r_unique(arg));
-           if (rb_respond_to(klass, s_alloc)) {
+           if (rb_obj_respond_to(klass, s_alloc, Qtrue)) {
 	       static int warn = Qtrue;
 	       if (warn) {
 		   rb_warn("define `allocate' instead of `_alloc'");
 		   warn = Qfalse;
 	       }
 	       v = rb_funcall(klass, s_alloc, 0);
+	       check_load_arg(arg);
            }
 	   else {
 	       v = rb_obj_alloc(klass);
@@ -1531,12 +1562,13 @@
                rb_raise(rb_eArgError, "dump format error");
            }
            v = r_entry(v, arg);
-           if (!rb_respond_to(v, s_load_data)) {
+           if (!rb_obj_respond_to(v, s_load_data, Qtrue)) {
                rb_raise(rb_eTypeError,
                         "class %s needs to have instance method `_load_data'",
                         rb_class2name(klass));
            }
            rb_funcall(v, s_load_data, 1, r_object0(arg, 0, extmod));
+	   check_load_arg(arg);
            v = r_leave(v, arg);
        }
        break;
@@ -1602,6 +1634,7 @@
 static VALUE
 load_ensure(struct load_arg *arg)
 {
+    if (!DATA_PTR(arg->compat_tbl_wrapper)) return 0;
     st_free_table(arg->symbols);
     st_free_table(arg->compat_tbl);
     DATA_PTR(arg->compat_tbl_wrapper) = 0;
@@ -1629,12 +1662,13 @@
     struct load_arg arg;
 
     rb_scan_args(argc, argv, "11", &port, &proc);
-    if (rb_respond_to(port, rb_intern("to_str"))) {
+    v = rb_check_string_type(port);
+    if (!NIL_P(v)) {
 	arg.taint = OBJ_TAINTED(port); /* original taintedness */
-	StringValue(port);	       /* possible conversion */
+	port = v;
     }
-    else if (rb_respond_to(port, s_getbyte) && rb_respond_to(port, s_read)) {
-	if (rb_respond_to(port, s_binmode)) {
+    else if (rb_obj_respond_to(port, s_getbyte, Qtrue) && rb_obj_respond_to(port, s_read, Qtrue)) {
+	if (rb_obj_respond_to(port, s_binmode, Qtrue)) {
 	    rb_funcall2(port, s_binmode, 0, 0);
 	}
 	arg.taint = Qtrue;

Modified: MacRuby/branches/testing/math.c
===================================================================
--- MacRuby/branches/testing/math.c	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/math.c	2008-06-05 08:33:02 UTC (rev 249)
@@ -2,7 +2,7 @@
 
   math.c -
 
-  $Author: matz $
+  $Author: nobu $
   created at: Tue Jan 25 14:12:56 JST 1994
 
   Copyright (C) 1993-2007 Yukihiro Matsumoto
@@ -35,7 +35,7 @@
 } while (0)
 
 static void
-domain_check(double x, char *msg)
+domain_check(double x, const char *msg)
 {
     while(1) {
 	if (errno) {
@@ -577,6 +577,10 @@
  *  but avoid overflow by Math.gamma(x) for large x.
  */
 
+#if WITH_OBJC && HAVE_LGAMMA_R && BYTE_ORDER == LITTLE_ENDIAN
+#  include "missing/lgamma_r.c"
+#endif
+
 static VALUE
 math_lgamma(VALUE obj, VALUE x)
 {

Modified: MacRuby/branches/testing/misc/ruby-mode.el
===================================================================
--- MacRuby/branches/testing/misc/ruby-mode.el	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/misc/ruby-mode.el	2008-06-05 08:33:02 UTC (rev 249)
@@ -5,7 +5,7 @@
 ;;;  created at: Fri Feb  4 14:49:13 JST 1994
 ;;;
 
-(defconst ruby-mode-revision "$Revision: 16266 $"
+(defconst ruby-mode-revision "$Revision: 16611 $"
   "Ruby mode revision string.")
 
 (defconst ruby-mode-version
@@ -312,7 +312,9 @@
   (set (make-local-variable 'font-lock-syntax-table) ruby-font-lock-syntax-table)
   (set (make-local-variable 'font-lock-syntactic-keywords) ruby-font-lock-syntactic-keywords)
 
-  (run-mode-hooks 'ruby-mode-hook))
+  (if (fboundp 'run-mode-hooks)
+      (run-mode-hooks 'ruby-mode-hook)
+    (run-hooks 'ruby-mode-hook)))
 
 (defun ruby-current-indentation ()
   (save-excursion

Modified: MacRuby/branches/testing/missing/crypt.c
===================================================================
--- MacRuby/branches/testing/missing/crypt.c	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/missing/crypt.c	2008-06-05 08:33:02 UTC (rev 249)
@@ -107,13 +107,15 @@
 #define	LARGEDATA
 #endif
 
+int des_setkey(), des_cipher();
+
 /* compile with "-DSTATIC=int" when profiling */
 #ifndef STATIC
 #define	STATIC	static
 #endif
-STATIC init_des(), init_perm(), permute();
+STATIC void init_des(), init_perm(), permute();
 #ifdef DEBUG
-STATIC prtab();
+STATIC void prtab();
 #endif
 
 /* ==================================== */
@@ -299,7 +301,7 @@
 #define	PERM3264(d,d0,d1,cpp,p)				\
 	{ C_block tblk; permute(cpp,&tblk,p,4); LOAD (d,d0,d1,tblk); }
 
-STATIC
+STATIC void
 permute(cp, out, p, chars_in)
 	unsigned char *cp;
 	C_block *out;
@@ -377,46 +379,62 @@
 };
 
 static unsigned char S[8][64] = {	/* 48->32 bit substitution tables */
+    {
 					/* S[1]			*/
 	14,  4, 13,  1,  2, 15, 11,  8,  3, 10,  6, 12,  5,  9,  0,  7,
 	 0, 15,  7,  4, 14,  2, 13,  1, 10,  6, 12, 11,  9,  5,  3,  8,
 	 4,  1, 14,  8, 13,  6,  2, 11, 15, 12,  9,  7,  3, 10,  5,  0,
 	15, 12,  8,  2,  4,  9,  1,  7,  5, 11,  3, 14, 10,  0,  6, 13,
+    },
+    {
 					/* S[2]			*/
 	15,  1,  8, 14,  6, 11,  3,  4,  9,  7,  2, 13, 12,  0,  5, 10,
 	 3, 13,  4,  7, 15,  2,  8, 14, 12,  0,  1, 10,  6,  9, 11,  5,
 	 0, 14,  7, 11, 10,  4, 13,  1,  5,  8, 12,  6,  9,  3,  2, 15,
 	13,  8, 10,  1,  3, 15,  4,  2, 11,  6,  7, 12,  0,  5, 14,  9,
+    },
+    {
 					/* S[3]			*/
 	10,  0,  9, 14,  6,  3, 15,  5,  1, 13, 12,  7, 11,  4,  2,  8,
 	13,  7,  0,  9,  3,  4,  6, 10,  2,  8,  5, 14, 12, 11, 15,  1,
 	13,  6,  4,  9,  8, 15,  3,  0, 11,  1,  2, 12,  5, 10, 14,  7,
 	 1, 10, 13,  0,  6,  9,  8,  7,  4, 15, 14,  3, 11,  5,  2, 12,
+    },
+    {
 					/* S[4]			*/
 	 7, 13, 14,  3,  0,  6,  9, 10,  1,  2,  8,  5, 11, 12,  4, 15,
 	13,  8, 11,  5,  6, 15,  0,  3,  4,  7,  2, 12,  1, 10, 14,  9,
 	10,  6,  9,  0, 12, 11,  7, 13, 15,  1,  3, 14,  5,  2,  8,  4,
 	 3, 15,  0,  6, 10,  1, 13,  8,  9,  4,  5, 11, 12,  7,  2, 14,
+    },
+    {
 					/* S[5]			*/
 	 2, 12,  4,  1,  7, 10, 11,  6,  8,  5,  3, 15, 13,  0, 14,  9,
 	14, 11,  2, 12,  4,  7, 13,  1,  5,  0, 15, 10,  3,  9,  8,  6,
 	 4,  2,  1, 11, 10, 13,  7,  8, 15,  9, 12,  5,  6,  3,  0, 14,
 	11,  8, 12,  7,  1, 14,  2, 13,  6, 15,  0,  9, 10,  4,  5,  3,
+    },
+    {
 					/* S[6]			*/
 	12,  1, 10, 15,  9,  2,  6,  8,  0, 13,  3,  4, 14,  7,  5, 11,
 	10, 15,  4,  2,  7, 12,  9,  5,  6,  1, 13, 14,  0, 11,  3,  8,
 	 9, 14, 15,  5,  2,  8, 12,  3,  7,  0,  4, 10,  1, 13, 11,  6,
 	 4,  3,  2, 12,  9,  5, 15, 10, 11, 14,  1,  7,  6,  0,  8, 13,
+    },
+    {
 					/* S[7]			*/
 	 4, 11,  2, 14, 15,  0,  8, 13,  3, 12,  9,  7,  5, 10,  6,  1,
 	13,  0, 11,  7,  4,  9,  1, 10, 14,  3,  5, 12,  2, 15,  8,  6,
 	 1,  4, 11, 13, 12,  3,  7, 14, 10, 15,  6,  8,  0,  5,  9,  2,
 	 6, 11, 13,  8,  1,  4, 10,  7,  9,  5,  0, 15, 14,  2,  3, 12,
+    },
+    {
 					/* S[8]			*/
 	13,  2,  8,  4,  6, 15, 11,  1, 10,  9,  3, 14,  5,  0, 12,  7,
 	 1, 15, 13,  8, 10,  3,  7,  4, 12,  5,  6, 11,  0, 14,  9,  2,
 	 7, 11,  4,  1,  9, 12, 14,  2,  0,  6, 10, 13, 15,  3,  5,  8,
 	 2,  1, 14,  7,  4, 10,  8, 13, 15, 12,  9,  0,  3,  5,  6, 11,
+    },
 };
 
 static unsigned char P32Tr[] = {	/* 32-bit permutation function */
@@ -580,6 +598,7 @@
 /*
  * Set up the key schedule from the key.
  */
+int
 des_setkey(key)
 	register const char *key;
 {
@@ -614,6 +633,7 @@
  * NOTE: the performance of this routine is critically dependent on your
  * compiler and machine architecture.
  */
+int
 des_cipher(in, out, salt, num_iter)
 	const char *in;
 	char *out;
@@ -734,7 +754,7 @@
  * Initialize various tables.  This need only be done once.  It could even be
  * done at compile time, if the compiler were capable of that sort of thing.
  */
-STATIC
+STATIC void
 init_des()
 {
 	register int i, j;
@@ -878,7 +898,7 @@
  *
  * "perm" must be all-zeroes on entry to this routine.
  */
-STATIC
+STATIC void
 init_perm(perm, p, chars_in, chars_out)
 	C_block perm[64/CHUNKBITS][1<<CHUNKBITS];
 	unsigned char p[64];
@@ -902,6 +922,7 @@
 /*
  * "setkey" routine (for backwards compatibility)
  */
+int
 setkey(key)
 	register const char *key;
 {
@@ -922,6 +943,7 @@
 /*
  * "encrypt" routine (for backwards compatibility)
  */
+int
 encrypt(block, flag)
 	register char *block;
 	int flag;
@@ -950,7 +972,7 @@
 }
 
 #ifdef DEBUG
-STATIC
+STATIC void
 prtab(s, t, num_rows)
 	char *s;
 	unsigned char *t;

Modified: MacRuby/branches/testing/missing/vsnprintf.c
===================================================================
--- MacRuby/branches/testing/missing/vsnprintf.c	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/missing/vsnprintf.c	2008-06-05 08:33:02 UTC (rev 249)
@@ -217,7 +217,7 @@
  * I/O descriptors for __sfvwrite().
  */
 struct __siov {
-	void	*iov_base;
+	const void *iov_base;
 	size_t	iov_len;
 };
 struct __suio {
@@ -422,7 +422,7 @@
  * use the given digits.
  */
 static char *
-BSD__ultoa(register u_long val, char *endp, int base, int octzero, char *xdigs)
+BSD__ultoa(register u_long val, char *endp, int base, int octzero, const char *xdigs)
 {
 	register char *cp = endp;
 	register long sval;
@@ -523,10 +523,10 @@
 static int
 BSD_vfprintf(FILE *fp, const char *fmt0, va_list ap)
 {
-	register char *fmt;	/* format string */
+	register const char *fmt; /* format string */
 	register int ch;	/* character from fmt */
 	register int n;		/* handy integer (short term usage) */
-	register char *cp;	/* handy char pointer (short term usage) */
+	register const char *cp;/* handy char pointer (short term usage) */
 	register struct __siov *iovp;/* for PRINT macro */
 	register int flags;	/* flags as above */
 	int ret;		/* return value accumulator */
@@ -550,12 +550,13 @@
 	int fieldsz;		/* field size expanded by sign, etc */
 	int realsz;		/* field size expanded by dprec */
 	int size;		/* size of converted field or string */
-	char *xdigs = 0;	/* digits for [xX] conversion */
+	const char *xdigs = 0;	/* digits for [xX] conversion */
 #define NIOV 8
 	struct __suio uio;	/* output information: summary */
 	struct __siov iov[NIOV];/* ... and individual io vectors */
 	char buf[BUF];		/* space for %c, %[diouxX], %[eEfgG] */
 	char ox[2];		/* space for 0x hex-prefix */
+	char *const ebuf = buf + sizeof(buf);
 
 	/*
 	 * Choose PADSIZE to trade efficiency vs. size.  If larger printf
@@ -616,7 +617,7 @@
 	    fp->_file >= 0)
 		return (BSD__sbprintf(fp, fmt0, ap));
 
-	fmt = (char *)fmt0;
+	fmt = fmt0;
 	uio.uio_iov = iovp = iov;
 	uio.uio_resid = 0;
 	uio.uio_iovcnt = 0;
@@ -720,7 +721,8 @@
 			goto rflag;
 #endif /* _HAVE_SANE_QUAD_ */
 		case 'c':
-			*(cp = buf) = va_arg(ap, int);
+			cp = buf;
+			*buf = (char)va_arg(ap, int);
 			size = 1;
 			sign = '\0';
 			break;
@@ -868,7 +870,7 @@
 				 * NUL in the first `prec' characters, and
 				 * strlen() will go further.
 				 */
-				char *p = (char *)memchr(cp, 0, prec);
+				const char *p = (char *)memchr(cp, 0, prec);
 
 				if (p != NULL) {
 					size = p - cp;
@@ -930,28 +932,27 @@
 			 * explicit precision of zero is no characters.''
 			 *	-- ANSI X3J11
 			 */
-			cp = buf + BUF;
 #ifdef _HAVE_SANE_QUAD_
 			if (flags & QUADINT) {
 				if (uqval != 0 || prec != 0)
-					cp = BSD__uqtoa(uqval, cp, base,
+					cp = BSD__uqtoa(uqval, ebuf, base,
 					    flags & ALT, xdigs);
 			} else
 #else /* _HAVE_SANE_QUAD_ */
 #endif /* _HAVE_SANE_QUAD_ */
 			{
 				if (ulval != 0 || prec != 0)
-					cp = BSD__ultoa(ulval, cp, base,
+					cp = BSD__ultoa(ulval, ebuf, base,
 					    flags & ALT, xdigs);
 			}
-			size = buf + BUF - cp;
+			size = ebuf - cp;
 			break;
 		default:	/* "%?" prints ?, unless ? is NUL */
 			if (ch == '\0')
 				goto done;
 			/* pretend it was %c with argument ch */
 			cp = buf;
-			*cp = ch;
+			*buf = ch;
 			size = 1;
 			sign = '\0';
 			break;

Modified: MacRuby/branches/testing/mkconfig.rb
===================================================================
--- MacRuby/branches/testing/mkconfig.rb	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/mkconfig.rb	2008-06-05 08:33:02 UTC (rev 249)
@@ -75,6 +75,7 @@
     next if /^\$ac_\w+$/ =~ val
     next if $install_name and /^RUBY_INSTALL_NAME$/ =~ name
     next if $so_name and /^RUBY_SO_NAME$/ =~  name
+    next if /^(?:X|(?:MINI|RUN)RUBY$)/ =~ name
     if /^program_transform_name$/ =~ name and /^s(\\?.)(.*)\1$/ =~ val
       next if $install_name
       sep = %r"#{Regexp.quote($1)}"

Modified: MacRuby/branches/testing/numeric.c
===================================================================
--- MacRuby/branches/testing/numeric.c	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/numeric.c	2008-06-05 08:33:02 UTC (rev 249)
@@ -2,7 +2,7 @@
 
   numeric.c -
 
-  $Author: matz $
+  $Author: akr $
   created at: Fri Aug 13 18:33:09 JST 1993
 
   Copyright (C) 1993-2007 Yukihiro Matsumoto
@@ -260,6 +260,20 @@
 }
 
 
+/*
+ *  call-seq:
+ *     num.fdiv(numeric)    =>   float
+ *
+ *  Returns float division.
+ */
+
+static VALUE
+num_fdiv(VALUE x, VALUE y)
+{
+    return rb_funcall(rb_Float(x), '/', 1, y);
+}
+
+
 static VALUE num_floor(VALUE num);
 
 /*
@@ -274,6 +288,7 @@
 static VALUE
 num_div(VALUE x, VALUE y)
 {
+    if (rb_equal(INT2FIX(0), y)) rb_num_zerodiv();
     return num_floor(rb_funcall(x, '/', 1, y));
 }
 
@@ -1559,22 +1574,14 @@
     else {
 	return;
     }
-#ifdef LONG_LONG_VALUE
-    rb_raise(rb_eRangeError, "integer %lld too %s to convert to `int'", num, s);
-#else
-    rb_raise(rb_eRangeError, "integer %ld too %s to convert to `int'", num, s);
-#endif
+    rb_raise(rb_eRangeError, "integer %"PRIdVALUE " too %s to convert to `int'", num, s);
 }
 
 static void
 check_uint(VALUE num)
 {
     if (num > UINT_MAX) {
-#ifdef LONG_LONG_VALUE
-	rb_raise(rb_eRangeError, "integer %llu too big to convert to `unsigned int'", num);
-#else
-	rb_raise(rb_eRangeError, "integer %lu too big to convert to `unsigned int'", num);
-#endif
+	rb_raise(rb_eRangeError, "integer %"PRIuVALUE " too big to convert to `unsigned int'", num);
     }
 }
 
@@ -1644,7 +1651,7 @@
 
     v = rb_num2long(val);
     if (!FIXABLE(v))
-	rb_raise(rb_eRangeError, "integer %ld out of range of fixnum", v);
+	rb_raise(rb_eRangeError, "integer %"PRIdVALUE " out of range of fixnum", v);
     return LONG2FIX(v);
 }
 
@@ -1863,7 +1870,9 @@
 int_chr(int argc, VALUE *argv, VALUE num)
 {
     char c;
+#if !WITH_OBJC
     int n;
+#endif
     long i = NUM2LONG(num);
     rb_encoding *enc;
     VALUE str;
@@ -1871,8 +1880,10 @@
     switch (argc) {
       case 0:
 	if (i < 0 || 0xff < i) {
+#if !WITH_OBJC
 	  out_of_range:
-	    rb_raise(rb_eRangeError, "%ld out of char range", i);
+#endif
+	    rb_raise(rb_eRangeError, "%"PRIdVALUE " out of char range", i);
 	}
 	c = i;
 	if (i < 0x80) {
@@ -1888,16 +1899,16 @@
 	break;
     }
 #if WITH_OBJC
-    /* TODO */
-    rb_notimplement();
+    enc = rb_to_encoding(argv[0]);
+    str = rb_enc_str_new(&c, 1, enc);
 #else
     enc = rb_to_encoding(argv[0]);
     if (!enc) enc = rb_ascii8bit_encoding();
     if (i < 0 || (n = rb_enc_codelen(i, enc)) <= 0) goto out_of_range;
     str = rb_enc_str_new(0, n, enc);
     rb_enc_mbcput(i, RSTRING_PTR(str), enc);
+#endif
     return str;
-#endif
 }
 
 static VALUE
@@ -2260,11 +2271,15 @@
 	return rb_big_div(x, y);
       case T_FLOAT:
 	{
-	    double div = (double)FIX2LONG(x) / RFLOAT_VALUE(y);
+	    double div;
+
 	    if (op == '/') {
+		div = (double)FIX2LONG(x) / RFLOAT_VALUE(y);
 		return DOUBLE2NUM(div);
 	    }
 	    else {
+		if (RFLOAT_VALUE(y) == 0) rb_num_zerodiv();
+		div = (double)FIX2LONG(x) / RFLOAT_VALUE(y);
 		return rb_dbl2big(floor(div));
 	    }
 	}
@@ -3114,7 +3129,7 @@
     rb_define_method(rb_cNumeric, "<=>", num_cmp, 1);
     rb_define_method(rb_cNumeric, "eql?", num_eql, 1);
     rb_define_method(rb_cNumeric, "quo", num_quo, 1);
-    rb_define_method(rb_cNumeric, "fdiv", num_quo, 1);
+    rb_define_method(rb_cNumeric, "fdiv", num_fdiv, 1);
     rb_define_method(rb_cNumeric, "div", num_div, 1);
     rb_define_method(rb_cNumeric, "divmod", num_divmod, 1);
     rb_define_method(rb_cNumeric, "modulo", num_modulo, 1);

Modified: MacRuby/branches/testing/objc.m
===================================================================
--- MacRuby/branches/testing/objc.m	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/objc.m	2008-06-05 08:33:02 UTC (rev 249)
@@ -69,6 +69,7 @@
 static struct st_table *bs_inf_prot_imethods;
 static struct st_table *bs_cftypes;
 
+#if 0
 static char *
 rb_objc_sel_to_mid(SEL selector, char *buffer, unsigned buffer_len)
 {
@@ -89,6 +90,7 @@
 
     return buffer;
 }
+#endif
 
 static inline const char *
 rb_objc_skip_octype_modifiers(const char *octype)
@@ -213,7 +215,6 @@
 static size_t
 get_ffi_struct_size(ffi_type *type)
 {
-    unsigned i;
     ffi_type **p;
     size_t s;
 
@@ -400,37 +401,7 @@
     return NULL;
 }
 
-#if 0
 static bool
-rb_primitive_obj_to_ocid(VALUE rval, id *ocval)
-{
-    if (TYPE(rval) == T_STRING) {
-	CFStringRef string;
-	CFStringEncoding cf_encoding;	
-	rb_encoding *enc;
-
-	enc = rb_enc_get(rval);
-	if (enc == NULL) {
-	    cf_encoding = kCFStringEncodingASCII;
-	}
-	else {
-	    /* TODO: support more encodings! */
-	    cf_encoding = kCFStringEncodingASCII;
-	}
-
-	string = CFStringCreateWithCStringNoCopy(
-	    NULL, RSTRING_PTR(rval), cf_encoding, kCFAllocatorNull);
-
-	*ocval = NSMakeCollectable(string);
-	return true;
-    }
-
-    rb_bug("cannot convert primitive obj `%s' to Objective-C",
-	   RSTRING_PTR(rb_inspect(rval)));
-}
-#endif
-
-static bool
 rb_objc_rval_to_ocid(VALUE rval, void **ocval)
 {
     if (!rb_special_const_p(rval) && rb_objc_is_non_native(rval)) {
@@ -545,6 +516,8 @@
 	*success = false;
 	return NULL;
     } 
+    
+    Data_Get_Struct(rval, void, data);
 
     if (bs_boxed->type == BS_ELEMENT_STRUCT) {
 	bs_element_struct_t *bs_struct;
@@ -557,25 +530,17 @@
 	 * could have been modified as a copy in the Ruby world.
 	 */
 	for (i = 0; i < bs_struct->fields_count; i++) {
-	    char buf[128];
-	    ID ivar_id;
-
-	    snprintf(buf, sizeof buf, "@%s", bs_struct->fields[i].name);
-	    ivar_id = rb_intern(buf);
-	    if (rb_ivar_defined(rval, ivar_id) == Qtrue) {
-		VALUE val;
-
-		val = rb_ivar_get(rval, ivar_id);
+	    VALUE *v;
+	    v = &((VALUE *)(data + bs_boxed->ffi_type->size))[i];
+	    if (*v != 0) {
+		char buf[512];
 		snprintf(buf, sizeof buf, "%s=", bs_struct->fields[i].name);
-		rb_funcall(rval, rb_intern(buf), 1, val);
-
-		//if (clean_ivars)
-		  //  rb_rval_remove_instance_variable(rval, ID2SYM(ivar_id));
+		rb_funcall(rval, rb_intern(buf), 1, *v);
+		*v = 0;
 	    }
 	}
     }
 
-    Data_Get_Struct(rval, void, data);
     *success = true;		
 
     return data;
@@ -596,6 +561,7 @@
 rb_bs_boxed_new_from_ocdata(bs_element_boxed_t *bs_boxed, void *ocval)
 {
     void *data;
+    size_t soffset;
 
     if (ocval == NULL)
 	return Qnil;
@@ -605,8 +571,15 @@
 
     rb_bs_boxed_assert_ffitype_ok(bs_boxed);
 
-    data = xmalloc(bs_boxed->ffi_type->size);
+    soffset = 0;
+    if (bs_boxed->type == BS_ELEMENT_STRUCT) {
+	soffset = ((bs_element_struct_t *)bs_boxed->value)->fields_count 
+		* sizeof(VALUE);
+    }
+
+    data = xmalloc(soffset + bs_boxed->ffi_type->size);
     memcpy(data, ocval, bs_boxed->ffi_type->size);
+    memset(data + bs_boxed->ffi_type->size, 0, soffset);
 
     return Data_Wrap_Struct(bs_boxed->klass, NULL, NULL, data);     
 }
@@ -617,8 +590,11 @@
     long n = 0;
     while ((*elements) != NULL) {
 	if ((*elements)->type == FFI_TYPE_STRUCT) {
-	    long i, n2 = rebuild_new_struct_ary((*elements)->elements, orig, new);
-	    VALUE tmp = rb_ary_new();
+	    long i, n2;
+	    VALUE tmp;
+
+	    n2 = rebuild_new_struct_ary((*elements)->elements, orig, new);
+	    tmp = rb_ary_new();
 	    for (i = 0; i < n2; i++) {
 		if (RARRAY_LEN(orig) == 0)
 		    return 0;
@@ -632,69 +608,91 @@
     return n;
 }
 
-static void
-rb_objc_rval_to_ocval(VALUE rval, const char *octype, void **ocval)
+static void rb_objc_rval_to_ocval(VALUE, const char *, void **);
+
+static void *
+rb_objc_rval_to_boxed_data(VALUE rval, bs_element_boxed_t *bs_boxed, bool *ok)
 {
-    bs_element_boxed_t *bs_boxed;
-    bool ok = true;
+    void *data;
 
-    octype = rb_objc_skip_octype_modifiers(octype);
+    if (TYPE(rval) == T_ARRAY && bs_boxed->type == BS_ELEMENT_STRUCT) {
+	bs_element_struct_t *bs_struct;
+	long i, n;
+	size_t pos;
 
-    if (*octype == _C_VOID)
-	return;
+	bs_struct = (bs_element_struct_t *)bs_boxed->value;
 
-    if (st_lookup(bs_boxeds, (st_data_t)octype, (st_data_t *)&bs_boxed)) {
-	void *data;
-	if (TYPE(rval) == T_ARRAY && bs_boxed->type == BS_ELEMENT_STRUCT) {
-	    bs_element_struct_t *bs_struct;
-	    long i, n;
-	    size_t pos;
+	rb_bs_boxed_assert_ffitype_ok(bs_boxed);
 
-	    bs_struct = (bs_element_struct_t *)bs_boxed->value;
-
-	    n = RARRAY_LEN(rval);
-	    if (n < bs_struct->fields_count)
-		rb_raise(rb_eArgError, 
+	n = RARRAY_LEN(rval);
+	if (n < bs_struct->fields_count)
+	    rb_raise(rb_eArgError, 
 		    "not enough elements in array `%s' to create " \
-		    "structure `%s' (%d for %d)", 
+		    "structure `%s' (%ld for %d)", 
 		    RSTRING_CPTR(rb_inspect(rval)), bs_struct->name, n, 
 		    bs_struct->fields_count);
-	    
-	    if (n > bs_struct->fields_count) {
-		VALUE new_rval = rb_ary_new();
-		VALUE orig = rval;
-		rval = rb_ary_dup(rval);
-		rebuild_new_struct_ary(bs_boxed->ffi_type->elements, rval, 
-				       new_rval);
-		n = RARRAY_LEN(new_rval);
-		if (RARRAY_LEN(rval) != 0 || n != bs_struct->fields_count) {
-		    rb_raise(rb_eArgError, 
+
+	if (n > bs_struct->fields_count) {
+	    VALUE new_rval = rb_ary_new();
+	    VALUE orig = rval;
+	    rval = rb_ary_dup(rval);
+	    rebuild_new_struct_ary(bs_boxed->ffi_type->elements, rval, 
+		    new_rval);
+	    n = RARRAY_LEN(new_rval);
+	    if (RARRAY_LEN(rval) != 0 || n != bs_struct->fields_count) {
+		rb_raise(rb_eArgError, 
 			"too much elements in array `%s' to create " \
-			"structure `%s' (%d for %d)", 
+			"structure `%s' (%ld for %d)", 
 			RSTRING_CPTR(rb_inspect(orig)), 
 			bs_struct->name, RARRAY_LEN(orig), 
 			bs_struct->fields_count);
-		}
-		rval = new_rval;
 	    }
+	    rval = new_rval;
+	}
 
-	    data = alloca(bs_boxed->ffi_type->size);
+	pos = bs_struct->fields_count * sizeof(VALUE);
+	data = xmalloc(bs_boxed->ffi_type->size + pos);
+	memset(data + bs_boxed->ffi_type->size, 0, pos);
+	pos = 0;
 
-	    for (i = 0, pos = 0; i < bs_struct->fields_count; i++) {
-		VALUE o = RARRAY_AT(rval, i);
-		char *field_type = bs_struct->fields[i].type;
-		rb_objc_rval_to_ocval(o, field_type, data + pos);
-		pos += rb_objc_octype_to_ffitype(field_type)->size;
-	    }
+	for (i = 0; i < bs_struct->fields_count; i++) {
+	    VALUE o = RARRAY_AT(rval, i);
+	    char *field_type = bs_struct->fields[i].type;
+	    rb_objc_rval_to_ocval(o, field_type, data + pos);
+	    pos += rb_objc_octype_to_ffitype(field_type)->size;
 	}
-	else {
-	    data = bs_element_boxed_get_data(bs_boxed, rval, &ok);
-	}
+
+	*ok = true;
+    }
+    else {
+	data = bs_element_boxed_get_data(bs_boxed, rval, ok);
+    }
+
+    return data;
+}
+
+static void
+rb_objc_rval_to_ocval(VALUE rval, const char *octype, void **ocval)
+{
+    bs_element_boxed_t *bs_boxed;
+    bool ok = true;
+
+    octype = rb_objc_skip_octype_modifiers(octype);
+
+    if (*octype == _C_VOID)
+	return;
+
+    if (st_lookup(bs_boxeds, (st_data_t)octype, (st_data_t *)&bs_boxed)) {
+	void *data;
+
+	data = rb_objc_rval_to_boxed_data(rval, bs_boxed, &ok);
 	if (ok) {
 	    if (data == NULL)
 		*(void **)ocval = NULL;
-	    else
+	    else {
 		memcpy(ocval, data, bs_boxed->ffi_type->size);
+		xfree(data);
+	    }
 	}
 	goto bails; 
     }
@@ -726,6 +724,14 @@
 	    else if (TYPE(rval) == T_STRING) {
 		*(char **)ocval = StringValuePtr(rval);
 	    }	
+	    else if (st_lookup(bs_boxeds, (st_data_t)octype + 1, 
+		     (st_data_t *)&bs_boxed)) {
+		void *data;
+
+		data = rb_objc_rval_to_boxed_data(rval, bs_boxed, &ok);
+		if (ok)
+		    *(void **)ocval = data;
+	    }
 	    else {
 		ok = false;
 	    }
@@ -827,7 +833,7 @@
     if (!ok)
     	rb_raise(rb_eArgError, "can't convert Ruby object `%s' to " \
 		 "Objective-C value of type `%s'", 
-		 RSTRING_PTR(rb_inspect(rval)), octype);
+		 RSTRING_CPTR(rb_inspect(rval)), octype);
 }
 
 VALUE
@@ -1082,12 +1088,12 @@
     real_count = count;
     if (bs_method != NULL && bs_method->variadic) {
 	if (RARRAY_LEN(argv) < count - 2)
-	    rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)",
+	    rb_raise(rb_eArgError, "wrong number of arguments (%ld for %d)",
 		RARRAY_LEN(argv), count - 2);
 	count = RARRAY_LEN(argv) + 2;
     }
     else if (RARRAY_LEN(argv) != count - 2) {
-	rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)",
+	rb_raise(rb_eArgError, "wrong number of arguments (%ld for %d)",
 		 RARRAY_LEN(argv), count - 2);
     }
 
@@ -1544,6 +1550,24 @@
     rb_funcall(ary, rb_intern("uniq!"), 0);
 }
 
+static bool
+rb_objc_resourceful(VALUE obj)
+{
+    /* TODO we should export this function in the runtime 
+     * Object#__resourceful__? perhaps? 
+     */
+    extern CFTypeID __CFGenericTypeID(void *);
+    CFTypeID t = __CFGenericTypeID((void *)obj);
+    if (t > 0) {
+	extern void *_CFRuntimeGetClassWithTypeID(CFTypeID);
+	long *d = (long *)_CFRuntimeGetClassWithTypeID(t);
+	/* first long is version, 4 means resourceful */
+	if (d != NULL && *d & 4)
+	    return true;	
+    }
+    return false;
+}
+
 static VALUE
 bs_function_dispatch(int argc, VALUE *argv, VALUE recv)
 {
@@ -1611,9 +1635,11 @@
     }
 
     resp = Qnil;
-    if (ffi_rettype != &ffi_type_void)
+    if (ffi_rettype != &ffi_type_void) {
 	rb_objc_ocval_to_rbval(ffi_ret, bs_func->retval->type, &resp);
-
+    	if (bs_func->retval->already_retained && !rb_objc_resourceful(resp))
+	    CFMakeCollectable((void *)resp);
+    }
     return resp;
 }
 
@@ -1685,14 +1711,16 @@
 	rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)",
 		 argc, bs_struct->fields_count);
 
-    data = (void *)xmalloc(bs_boxed->ffi_type->size);
-    memset(data, 0, bs_boxed->ffi_type->size);
+    pos = bs_struct->fields_count * sizeof(VALUE);
+    data = (void *)xmalloc(pos + bs_boxed->ffi_type->size);
+    memset(data, 0, pos + bs_boxed->ffi_type->size);
+    pos = 0;
 
-    for (i = 0, pos = 0; i < argc; i++) {
+    for (i = 0; i < argc; i++) {
 	bs_element_struct_field_t *bs_field = 
 	    (bs_element_struct_field_t *)&bs_struct->fields[i];
 
-	rb_objc_rval_to_ocval(argv[i], bs_field->type, data + pos);	
+	rb_objc_rval_to_ocval(argv[i], bs_field->type, data + pos);
     
         pos += rb_objc_octype_to_ffitype(bs_field->type)->size;
     }
@@ -1714,10 +1742,11 @@
     return rb_intern(ivar_name);
 }
 
-static void *
-rb_bs_struct_get_field_data(bs_element_struct_t *bs_struct, VALUE recv,
-			    ID ivar_id, char **octype)
+static VALUE
+rb_bs_struct_get(VALUE recv)
 {
+    bs_element_boxed_t *bs_boxed = rb_klass_get_bs_boxed(CLASS_OF(recv));
+    bs_element_struct_t *bs_struct = (bs_element_struct_t *)bs_boxed->value;
     unsigned i;
     const char *ivar_id_str;
     void *data;
@@ -1727,67 +1756,75 @@
      * bs_element_struct_fields 
      */
 
-    ivar_id_str = rb_id2name(ivar_id);
+    ivar_id_str = rb_id2name(rb_bs_struct_field_ivar_id());
     ivar_id_str++; /* skip first '@' */
 
     Data_Get_Struct(recv, void, data);
     assert(data != NULL);
 
+    rb_objc_wb_range(data + bs_boxed->ffi_type->size,
+		     bs_struct->fields_count * sizeof(VALUE));
+
     for (i = 0, pos = 0; i < bs_struct->fields_count; i++) {
 	bs_element_struct_field_t *bs_field =
 	    (bs_element_struct_field_t *)&bs_struct->fields[i];
+
 	if (strcmp(ivar_id_str, bs_field->name) == 0) {
-	    *octype = bs_field->type;
-	    return data + pos;   
+	    VALUE *val;
+
+	    val = &((VALUE *)(data + bs_boxed->ffi_type->size))[i];
+	    if (*val == 0)
+		rb_objc_ocval_to_rbval(data + pos, bs_field->type, val);
+	    return *val;
 	}
         pos += rb_objc_octype_to_ffitype(bs_field->type)->size;
     }
 
     rb_bug("can't find field `%s' in recv `%s'", ivar_id_str,
-	   RSTRING_PTR(rb_inspect(recv)));
+	   RSTRING_CPTR(rb_inspect(recv)));
+
+    return Qnil;
 }
 
 static VALUE
-rb_bs_struct_get(VALUE recv)
+rb_bs_struct_set(VALUE recv, VALUE value)
 {
     bs_element_boxed_t *bs_boxed = rb_klass_get_bs_boxed(CLASS_OF(recv));
-    bs_element_struct_t *bs_struct = (bs_element_struct_t *)bs_boxed->value;    
-    ID ivar_id;
-    VALUE result;
+    bs_element_struct_t *bs_struct = (bs_element_struct_t *)bs_boxed->value;
+    unsigned i;
+    const char *ivar_id_str;
+    void *data;
+    size_t pos;
 
-    ivar_id = rb_bs_struct_field_ivar_id();
+    /* FIXME we should cache the ivar IDs somewhere in the 
+     * bs_element_struct_fields 
+     */
 
-    if (rb_ivar_defined(recv, ivar_id) == Qfalse) {
-	void *data;
-	char *octype;
-	BOOL ok;
+    ivar_id_str = rb_id2name(rb_bs_struct_field_ivar_id());
+    ivar_id_str++; /* skip first '@' */
 
-	data = rb_bs_struct_get_field_data(bs_struct, recv, ivar_id, &octype);
-	rb_objc_ocval_to_rbval(data, octype, &result);
-	rb_ivar_set(recv, ivar_id, result);
-    }
-    else {
-	result = rb_ivar_get(recv, ivar_id);
-    }
-   
-     return result;
-}
+    Data_Get_Struct(recv, void, data);
+    assert(data != NULL);
 
-static VALUE
-rb_bs_struct_set(VALUE recv, VALUE value)
-{
-    bs_element_boxed_t *bs_boxed = rb_klass_get_bs_boxed(CLASS_OF(recv));
-    bs_element_struct_t *bs_struct = (bs_element_struct_t *)bs_boxed->value;    
-    ID ivar_id;
-    void *data;
-    char *octype;
+    for (i = 0, pos = 0; i < bs_struct->fields_count; i++) {
+	bs_element_struct_field_t *bs_field =
+	    (bs_element_struct_field_t *)&bs_struct->fields[i];
 
-    ivar_id = rb_bs_struct_field_ivar_id();
-    data = rb_bs_struct_get_field_data(bs_struct, recv, ivar_id, &octype);
-    rb_objc_rval_to_ocval(value, octype, data);
-    rb_ivar_set(recv, ivar_id, value);
+	if (strcmp(ivar_id_str, bs_field->name) == 0) {
+	    rb_objc_rval_to_ocval(value, bs_field->type, data + pos);
+	    /* We do not update the cache because `value' may have been
+	     * transformed (ex. fixnum to float).
+	     */
+	    ((VALUE *)(data + bs_boxed->ffi_type->size))[i] = 0;
+	    return value;
+	}
+        pos += rb_objc_octype_to_ffitype(bs_field->type)->size;
+    }
 
-    return value;    
+    rb_bug("can't find field `%s' in recv `%s'", ivar_id_str,
+	   RSTRING_CPTR(rb_inspect(recv)));
+
+    return Qnil;
 }
 
 static VALUE
@@ -1813,7 +1850,6 @@
 static VALUE
 rb_bs_boxed_is_equal(VALUE recv, VALUE other)
 {
-    unsigned i;
     bs_element_boxed_t *bs_boxed;  
     bool ok;
     void *d1, *d2; 
@@ -1831,12 +1867,12 @@
     d1 = bs_element_boxed_get_data(bs_boxed, recv, &ok);
     if (!ok)
 	rb_raise(rb_eRuntimeError, "can't retrieve data for boxed `%s'",
-		 RSTRING_PTR(rb_inspect(recv)));
+		 RSTRING_CPTR(rb_inspect(recv)));
 
     d2 = bs_element_boxed_get_data(bs_boxed, other, &ok);
     if (!ok)
 	rb_raise(rb_eRuntimeError, "can't retrieve data for boxed `%s'",
-		 RSTRING_PTR(rb_inspect(recv)));
+		 RSTRING_CPTR(rb_inspect(recv)));
 
     if (d1 == d2)
 	return Qtrue;
@@ -1850,21 +1886,18 @@
 rb_bs_struct_dup(VALUE recv)
 {
     bs_element_boxed_t *bs_boxed = rb_klass_get_bs_boxed(CLASS_OF(recv));
-    void *data, *newdata;
+    void *data;
     bool ok;
 
     data = bs_element_boxed_get_data(bs_boxed, recv, &ok);
     if (!ok)
 	rb_raise(rb_eRuntimeError, "can't retrieve data for boxed `%s'",
-		 RSTRING_PTR(rb_inspect(recv)));
+		 RSTRING_CPTR(rb_inspect(recv)));
 
     if (data == NULL)
 	return Qnil;
 
-    newdata = xmalloc(sizeof(bs_boxed->ffi_type->size));
-    memcpy(newdata, data, bs_boxed->ffi_type->size);
-
-    return rb_bs_boxed_new_from_ocdata(bs_boxed, newdata);
+    return rb_bs_boxed_new_from_ocdata(bs_boxed, data);
 }
 
 static VALUE
@@ -1872,7 +1905,6 @@
 {
     bs_element_boxed_t *bs_boxed = rb_klass_get_bs_boxed(CLASS_OF(recv));
     bs_element_struct_t *bs_struct = (bs_element_struct_t *)bs_boxed->value;    
-    VALUE ary;
     unsigned i;
     VALUE str;
 
@@ -2203,21 +2235,11 @@
 {
     char path[PATH_MAX];
     char *error;
-    char *p;
 
     if (bs_find_path(framework_path, path, sizeof path)) {
-	if (!bs_parse(path, 0, bs_parse_cb, NULL, &error))
+	if (!bs_parse(path, BS_PARSE_OPTIONS_LOAD_DYLIBS, bs_parse_cb, NULL, 
+		      &error))
 	    rb_raise(rb_eRuntimeError, error);
-#if 0
-	/* FIXME 'GC capability mismatch' with .dylib files */
-	p = strrchr(path, '.');
-	assert(p != NULL);
-	strlcpy(p, ".dylib", p - path - 1);
-	if (access(path, R_OK) == 0) {
-	    if (dlopen(path, RTLD_LAZY) == NULL)
-		rb_raise(rb_eRuntimeError, dlerror());
-	}
-#endif
     }
 }
 
@@ -2247,7 +2269,6 @@
     class_count = count;
 }
 
-static void dyld_add_image_cb(const struct mach_header* mh, intptr_t vmaddr_slide);
 VALUE
 rb_require_framework(int argc, VALUE *argv, VALUE recv)
 {
@@ -2262,7 +2283,7 @@
     rb_scan_args(argc, argv, "11", &framework, &search_network);
 
     Check_Type(framework, T_STRING);
-    cstr = RSTRING_PTR(framework);
+    cstr = RSTRING_CPTR(framework);
 
     fileManager = [NSFileManager defaultManager];
     path = [fileManager stringWithFileSystemRepresentation:cstr
@@ -2296,6 +2317,12 @@
 
 	frameworkName = [path stringByAppendingPathExtension:@"framework"];
 
+	path = [[[[NSBundle mainBundle] bundlePath] 
+	    stringByAppendingPathComponent:@"Contents/Frameworks"] 
+		stringByAppendingPathComponent:frameworkName];
+	if ([fileManager fileExistsAtPath:path])
+	    goto success;	
+
 	dirs = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, 
 	    pathDomainMask, YES);
 	for (i = 0, count = [dirs count]; i < count; i++) {
@@ -2314,7 +2341,7 @@
 #undef FIND_LOAD_PATH_IN_LIBRARY
 
 	rb_raise(rb_eRuntimeError, "framework `%s' not found", 
-	    RSTRING_PTR(framework));
+	    RSTRING_CPTR(framework));
     }
 
 success:
@@ -2368,7 +2395,7 @@
     if (!ok)
 	[NSException raise:@"NSException" 
 	    format:@"can't get internal data for boxed type `%s'",
-	    RSTRING_PTR(rb_inspect((VALUE)rcv))];
+	    RSTRING_CPTR(rb_inspect((VALUE)rcv))];
     if (data == NULL) {
 	*(void **)buffer = NULL; 
     }
@@ -2439,7 +2466,7 @@
 {
     const char *name;
     size_t len;
-    char buf[100];    
+    char buf[100];
 
     if (mid == 0)
 	return mid;
@@ -2475,10 +2502,11 @@
 	strlcpy(buf, name, sizeof buf);
 	buf[len - 1] = '\0';
     }
-    else
+    else {
 	return mid;
+    }
 
-//    printf("new sel %s for %s\n", buf, name);
+    //printf("new sel %s for %s\n", buf, name);
 
     return rb_intern(buf);	
 }
@@ -2584,42 +2612,9 @@
 	    rb_raise(rb_eArgError, "can't register `%s' as an IB outlet",
 		     symname);
     }
+    return recv;
 }
 
-#if 0
-static void
-dyld_add_image_cb(const struct mach_header* mh, intptr_t vmaddr_slide)
-{
-    reload_class_constants();
-}
-#endif
-
-#if 0
-/* XXX the ivar cluster API is not used yet, and may not simply be used. 
- */
-#define IVAR_CLUSTER_NAME "__rivars__"
-void
-rb_objc_install_ivar_cluster(Class klass)
-{
-    assert(class_addIvar(klass, IVAR_CLUSTER_NAME, sizeof(void *), 
-	log2(sizeof(void *)), "^v") == YES);
-}
-
-void *
-rb_objc_get_ivar_cluster(void *obj)
-{
-    void *v = NULL;
-    assert(object_getInstanceVariable((id)obj, IVAR_CLUSTER_NAME, &v) != NULL);
-    return v;
-}
-
-void
-rb_objc_set_ivar_cluster(void *obj, void *v)
-{
-    assert(object_setInstanceVariable((id)obj, IVAR_CLUSTER_NAME, v) != NULL);
-}
-#endif
-
 static CFMutableDictionaryRef __obj_flags;
 
 long
@@ -2898,10 +2893,10 @@
     rb_objc_retain(bs_inf_prot_imethods = st_init_numtable());
     rb_objc_retain(bs_cftypes = st_init_strtable());
 
-    rb_objc_retain(
-	bs_const_magic_cookie = rb_str_new2("bs_const_magic_cookie"));
-    rb_objc_retain(
-	rb_objc_class_magic_cookie = rb_str_new2("rb_objc_class_magic_cookie"));
+    rb_objc_retain((const void *)(
+	bs_const_magic_cookie = rb_str_new2("bs_const_magic_cookie")));
+    rb_objc_retain((const void *)(
+	rb_objc_class_magic_cookie = rb_str_new2("rb_objc_class_magic_cookie")));
 
     rb_cBoxed = rb_define_class("Boxed",
 	rb_objc_import_class(objc_getClass("NSValue")));
@@ -2914,10 +2909,6 @@
     rb_install_objc_primitives();
     rb_install_alloc_methods();
 
-#if 0 /* FIXME this doesn't seem to work as expected */
-    _dyld_register_func_for_add_image(dyld_add_image_cb);
-#endif
-
     rb_define_global_function("load_bridge_support_file", rb_objc_load_bs, 1);
 
     {

Modified: MacRuby/branches/testing/object.c
===================================================================
--- MacRuby/branches/testing/object.c	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/object.c	2008-06-05 08:33:02 UTC (rev 249)
@@ -2,7 +2,7 @@
 
   object.c -
 
-  $Author: matz $
+  $Author: nobu $
   created at: Thu Jul 15 12:01:24 JST 1993
 
   Copyright (C) 1993-2007 Yukihiro Matsumoto
@@ -159,8 +159,8 @@
 {
 #if WITH_OBJC
     if (rb_objc_is_non_native(obj)) {
-	if (rb_objc_flag_check(obj, FL_TAINT))
-	    rb_objc_flag_set(dest, FL_TAINT);
+	if (rb_objc_flag_check((const void *)obj, FL_TAINT))
+	    rb_objc_flag_set((const void *)dest, FL_TAINT, true);
 	goto call_init_copy;
     }
 #endif
@@ -318,7 +318,7 @@
 VALUE
 rb_any_to_s(VALUE obj)
 {
-    char *cname = rb_obj_classname(obj);
+    const char *cname = rb_obj_classname(obj);
     VALUE str;
 
     str = rb_sprintf("#<%s:%p>", cname, (void*)obj);
@@ -419,9 +419,8 @@
 
         if (has_ivar) {
             VALUE str;
-            char *c;
+            const char *c = rb_obj_classname(obj);
 
-            c = rb_obj_classname(obj);
             str = rb_sprintf("-<%s:%p", c, (void*)obj);
             return rb_exec_recursive(inspect_obj, obj, str);
         }
@@ -679,7 +678,7 @@
 {
 #if WITH_OBJC
     if (!SPECIAL_CONST_P(obj) && rb_objc_is_non_native(obj)) {
-	return rb_objc_flag_check(obj, FL_TAINT) ? Qtrue : Qfalse;
+	return rb_objc_flag_check((const void *)obj, FL_TAINT) ? Qtrue : Qfalse;
     }
 #endif
     if (FL_TEST(obj, FL_TAINT))
@@ -702,7 +701,7 @@
     rb_secure(4);
 #if WITH_OBJC
     if (!SPECIAL_CONST_P(obj) && rb_objc_is_non_native(obj)) {
-	rb_objc_flag_set(obj, FL_TAINT, true);
+	rb_objc_flag_set((const void *)obj, FL_TAINT, true);
 	return obj;
     }
 #endif
@@ -729,7 +728,7 @@
     rb_secure(3);
 #if WITH_OBJC
     if (!SPECIAL_CONST_P(obj) && rb_objc_is_non_native(obj)) {
-	rb_objc_flag_set(obj, FL_TAINT, false);
+	rb_objc_flag_set((const void *)obj, FL_TAINT, false);
 	return obj;
     }
 #endif
@@ -785,7 +784,7 @@
 	}
 #if WITH_OBJC
 	else if (rb_objc_is_non_native(obj)) {
-	    rb_objc_flag_set(obj, FL_FREEZE, true);
+	    rb_objc_flag_set((const void *)obj, FL_FREEZE, true);
 	}
 #endif
 	else {
@@ -816,7 +815,8 @@
     }
 #if WITH_OBJC
     if (rb_objc_is_non_native(obj)) {
-	return rb_objc_is_immutable(obj) || rb_objc_flag_check(obj, FL_FREEZE)
+	return rb_objc_is_immutable(obj) 
+	    || rb_objc_flag_check((const void *)obj, FL_FREEZE)
 	    ? Qtrue : Qfalse;
     }
 #endif
@@ -1976,7 +1976,7 @@
     ID m;
 
     m = rb_intern(method);
-    if (!rb_respond_to(val, m)) {
+    if (!rb_obj_respond_to(val, m, Qtrue)) {
 	if (raise) {
 	    rb_raise(rb_eTypeError, "can't convert %s into %s",
 		     NIL_P(val) ? "nil" :
@@ -2000,7 +2000,7 @@
     if (TYPE(val) == type) return val;
     v = convert_type(val, tname, method, Qtrue);
     if (TYPE(v) != type) {
-	char *cname = rb_obj_classname(val);
+	const char *cname = rb_obj_classname(val);
 	rb_raise(rb_eTypeError, "can't convert %s to %s (%s#%s gives %s)",
 		 cname, tname, cname, method, rb_obj_classname(v));
     }
@@ -2017,7 +2017,7 @@
     v = convert_type(val, tname, method, Qfalse);
     if (NIL_P(v)) return Qnil;
     if (TYPE(v) != type) {
-	char *cname = rb_obj_classname(val);
+	const char *cname = rb_obj_classname(val);
 	rb_raise(rb_eTypeError, "can't convert %s to %s (%s#%s gives %s)",
 		 cname, tname, cname, method, rb_obj_classname(v));
     }
@@ -2033,7 +2033,7 @@
     if (FIXNUM_P(val)) return val;
     v = convert_type(val, "Integer", method, Qtrue);
     if (!rb_obj_is_kind_of(v, rb_cInteger)) {
-	char *cname = rb_obj_classname(val);
+	const char *cname = rb_obj_classname(val);
 	rb_raise(rb_eTypeError, "can't convert %s to Integer (%s#%s gives %s)",
 		 cname, cname, method, rb_obj_classname(v));
     }

Modified: MacRuby/branches/testing/pack.c
===================================================================
--- MacRuby/branches/testing/pack.c	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/pack.c	2008-06-05 08:33:02 UTC (rev 249)
@@ -12,6 +12,7 @@
 #include "ruby/ruby.h"
 #include <sys/types.h>
 #include <ctype.h>
+#include <errno.h>
 
 #define SIZE16 2
 #define SIZE32 4
@@ -478,7 +479,7 @@
 	    continue;
 	}
         if (*p == '_' || *p == '!') {
-	    const char *natstr = "sSiIlL";
+	    static const char natstr[] = "sSiIlL";
 
 	    if (strchr(natstr, type)) {
 #ifdef NATINT_PACK
@@ -495,7 +496,11 @@
 	    p++;
 	}
 	else if (ISDIGIT(*p)) {
+	    errno = 0;
 	    len = STRTOUL(p, (char**)&p, 10);
+	    if (errno) {
+		rb_raise(rb_eRangeError, "pack length too big");
+	    }
 	}
 	else {
 	    len = 1;
@@ -1338,7 +1343,7 @@
 	}
 	star = 0;
 	if (*p == '_' || *p == '!') {
-	    const char *natstr = "sSiIlL";
+	    static const char natstr[] = "sSiIlL";
 
 	    if (strchr(natstr, type)) {
 #ifdef NATINT_PACK
@@ -1358,7 +1363,11 @@
 	    p++;
 	}
 	else if (ISDIGIT(*p)) {
+	    errno = 0;
 	    len = STRTOUL(p, (char**)&p, 10);
+	    if (errno) {
+		rb_raise(rb_eRangeError, "pack length too big");
+	    }
 	}
 	else {
 	    len = (type != '@');
@@ -1565,7 +1574,6 @@
 	    }
 	    PACK_ITEM_ADJUST();
 	    break;
-
 	  case 'L':
 	    PACK_LENGTH_ADJUST(unsigned long,4);
 	    while (len-- > 0) {
@@ -1586,7 +1594,6 @@
 	    }
 	    PACK_ITEM_ADJUST();
 	    break;
-
 	  case 'Q':
 	    PACK_LENGTH_ADJUST_SIZE(QUAD_SIZE);
 	    while (len-- > 0) {

Modified: MacRuby/branches/testing/parse.y
===================================================================
--- MacRuby/branches/testing/parse.y	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/parse.y	2008-06-05 08:33:02 UTC (rev 249)
@@ -2,7 +2,7 @@
 
   parse.y -
 
-  $Author: usa $
+  $Author: mame $
   created at: Fri May 28 18:02:42 JST 1993
 
   Copyright (C) 1993-2007 Yukihiro Matsumoto
@@ -433,8 +433,10 @@
 static int arg_var_gen(struct parser_params*, ID);
 #define arg_var(id) arg_var_gen(parser, id)
 #if WITH_OBJC
-static int named_arg_gen(struct parser_params*, ID, int);
+static void named_arg_gen(struct parser_params*, ID, int);
 # define named_arg(id, flag) named_arg_gen(parser, id, flag)
+static NODE *process_named_args_gen(struct parser_params*, NODE*);
+# define process_named_args(node) process_named_args_gen(parser, node)
 #endif
 static int  local_id_gen(struct parser_params*, ID);
 #define local_id(id) local_id_gen(parser, id)
@@ -6198,8 +6200,10 @@
     }
     pushback(c);
     parser->enc = rb_enc_get(lex_lastline);
-#if !WITH_OBJC
     if (parser->enc == NULL)
+#if WITH_OBJC
+	parser->enc = rb_locale_encoding();
+#else
 	parser->enc = rb_utf8_encoding();
 #endif
 }
@@ -6215,7 +6219,9 @@
     int cmd_state;
     enum lex_state_e last_state;
     rb_encoding *enc;
+#if !WITH_OBJC
     int mb;
+#endif
 #ifdef RIPPER
     int fallthru = Qfalse;
 #endif
@@ -7937,7 +7943,9 @@
     else if (is_class_id(id)) {
 	return NEW_CVASGN(id, val);
     }
-    compile_error(PARSER_ARG "identifier %s is not valid to set", rb_id2name(id));
+    else {
+	compile_error(PARSER_ARG "identifier %s is not valid to set", rb_id2name(id));
+    }
     return 0;
 }
 
@@ -8663,7 +8671,47 @@
 }
 
 #if WITH_OBJC
-static int
+static NODE *
+process_named_args_gen(struct parser_params *parser, NODE *n)
+{
+    NODE *args = n->nd_args;
+    if (args != NULL 
+	&& args->nd_argc == 2 
+	&& nd_type(args->u3.node->u1.node) == NODE_ARRAY
+	&& args->u3.node->u1.node->flags & NODE_ARRAY_NAMED_ARGS) {
+
+	NODE *named_args;
+	NODE *new_argv;
+	NODE *p;
+	char buf[512];
+	bool flip;	
+
+	new_argv = NEW_LIST(args->nd_head);
+
+	strlcpy(buf, rb_id2name(n->u2.id), sizeof buf);
+	strlcat(buf, ":", sizeof buf);
+	
+	named_args = args->u3.node->u1.node;
+	for (flip = true, p = named_args; 
+	     p != NULL; 
+	     p = p->nd_next, flip = !flip) {
+	    if (flip) {
+		strlcat(buf, rb_id2name(SYM2ID(p->nd_head->nd_lit)), 
+			sizeof buf);
+		strlcat(buf, ":", sizeof buf);
+	    }
+	    else {
+		list_append(new_argv, p->nd_head);
+	    }	    
+	}
+
+	n->nd_mid = rb_intern(buf);
+	n->nd_args = new_argv;
+    }
+    return n;
+}
+
+static void
 named_arg_gen(struct parser_params *parser, ID id, int init)
 {
     if (init)
@@ -9093,7 +9141,6 @@
 Init_sym(void)
 {
 #if WITH_OBJC
-    CFDictionaryKeyCallBacks cb;
     global_symbols.sym_id = CFDictionaryCreateMutable(NULL,
 	0, NULL, NULL);
     GC_ROOT(&global_symbols.sym_id);
@@ -9644,7 +9691,7 @@
     parser->heap = NULL;
 #endif
 #if WITH_OBJC
-    parser->enc = NULL;
+    parser->enc = rb_locale_encoding();
 #else
     parser->enc = rb_usascii_encoding();
 #endif
@@ -9658,7 +9705,9 @@
 static void
 parser_mark(void *ptr)
 {
+#if !WITH_OBJC
     struct parser_params *p = (struct parser_params*)ptr;
+#endif
 
     rb_gc_mark((VALUE)p->parser_lex_strterm);
     rb_gc_mark(p->parser_lex_input);

Modified: MacRuby/branches/testing/proc.c
===================================================================
--- MacRuby/branches/testing/proc.c	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/proc.c	2008-06-05 08:33:02 UTC (rev 249)
@@ -2,7 +2,7 @@
 
   proc.c - Proc, Binding, Env
 
-  $Author: matz $
+  $Author: nobu $
   created at: Wed Jan 17 12:13:14 2007
 
   Copyright (C) 2004-2007 Koichi Sasada
@@ -50,7 +50,6 @@
 	proc = ptr;
 	RUBY_MARK_UNLESS_NULL(proc->envval);
 	RUBY_MARK_UNLESS_NULL(proc->blockprocval);
-	RUBY_MARK_UNLESS_NULL((VALUE)proc->special_cref_stack);
 	RUBY_MARK_UNLESS_NULL(proc->block.proc);
 	RUBY_MARK_UNLESS_NULL(proc->block.self);
 	if (proc->block.iseq && RUBY_VM_IFUNC_P(proc->block.iseq)) {
@@ -93,8 +92,7 @@
     dst->block = src->block;
     dst->block.proc = procval;
     dst->envval = src->envval;
-    dst->safe_level = dst->safe_level;
-    dst->special_cref_stack = src->special_cref_stack;
+    dst->safe_level = src->safe_level;
     dst->is_lambda = src->is_lambda;
 
     return procval;
@@ -241,7 +239,6 @@
     if (ptr) {
 	bind = ptr;
 	RUBY_MARK_UNLESS_NULL(bind->env);
-	RUBY_MARK_UNLESS_NULL((VALUE)bind->cref_stack);
     }
     RUBY_MARK_LEAVE("binding");
 }
@@ -264,7 +261,6 @@
     GetBindingPtr(self, src);
     GetBindingPtr(bindval, dst);
     dst->env = src->env;
-    dst->cref_stack = src->cref_stack;
     return bindval;
 }
 
@@ -286,7 +282,6 @@
 
     GetBindingPtr(bindval, bind);
     GC_WB(&bind->env, vm_make_env_object(th, cfp));
-    GC_WB(&bind->cref_stack, ruby_cref());
     return bindval;
 }
 
@@ -666,7 +661,7 @@
 {
     VALUE str = 0;
     rb_proc_t *proc;
-    char *cname = rb_obj_classname(self);
+    const char *cname = rb_obj_classname(self);
     rb_iseq_t *iseq;
     const char *is_lambda;
     
@@ -710,23 +705,6 @@
     return self;
 }
 
-/*
- *  call-seq:
- *     prc.binding    => binding
- *  
- *  Returns the binding associated with <i>prc</i>. Note that
- *  <code>Kernel#eval</code> accepts either a <code>Proc</code> or a
- *  <code>Binding</code> object as its second parameter.
- *     
- *     def fred(param)
- *       proc {}
- *     end
- *     
- *     b = fred(99)
- *     eval("param", b.binding)   #=> 99
- *     eval("param", b)           #=> 99
- */
-
 static void
 bm_mark(struct METHOD *data)
 {
@@ -1208,10 +1186,12 @@
 	}
     }
     if ((state = EXEC_TAG()) == 0) {
+	VALUE rb_vm_call(rb_thread_t * th, VALUE klass, VALUE recv, VALUE id, ID oid,
+			 int argc, const VALUE *argv, const NODE *body, int nosuper);
+
 	PASS_PASSED_BLOCK();
-	result = vm_call0(GET_THREAD(),
-			  data->oclass, data->recv, data->id, data->oid,
-			  argc, argv, data->body, 0);
+	result = rb_vm_call(GET_THREAD(), data->oclass, data->recv, data->id, data->oid,
+			    argc, argv, data->body, 0);
     }
     POP_TAG();
     if (safe >= 0)
@@ -1447,7 +1427,7 @@
     struct METHOD *data;
     VALUE str;
     const char *s;
-    char *sharp = "#";
+    const char *sharp = "#";
 
     Data_Get_Struct(method, struct METHOD, data);
     str = rb_str_buf_new2("#<");
@@ -1615,12 +1595,11 @@
     GetProcPtr(self, proc);
     GetBindingPtr(bindval, bind);
 
-    if (BUILTIN_TYPE(proc->block.iseq) == T_NODE) {
+    if (TYPE(proc->block.iseq) == T_NODE) {
 	rb_raise(rb_eArgError, "Can't create Binding from C level Proc");
     }
 
     bind->env = proc->envval;
-    bind->cref_stack = proc->special_cref_stack;
     return bindval;
 }
 

Modified: MacRuby/branches/testing/process.c
===================================================================
--- MacRuby/branches/testing/process.c	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/process.c	2008-06-05 08:33:02 UTC (rev 249)
@@ -2676,6 +2676,10 @@
     else {
 	status = proc_spawn_n(argc, argv, prog);
     }
+#  if defined(_WIN32)
+    if (status == -1)
+	rb_last_status_set(0x7f << 8, 0);
+#  endif
 # else
     if (argc) prog = rb_ary_join(rb_ary_new4(argc, argv), rb_str_new2(" "));
     status = system(StringValuePtr(prog));

Modified: MacRuby/branches/testing/rational.c
===================================================================
--- MacRuby/branches/testing/rational.c	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/rational.c	2008-06-05 08:33:02 UTC (rev 249)
@@ -1371,7 +1371,7 @@
 	    VALUE l;
 
 	    while (*p) {
-		if (isdigit(*p))
+		if (rb_isdigit(*p))
 		    count++;
 		p++;
 	    }

Modified: MacRuby/branches/testing/re.c
===================================================================
--- MacRuby/branches/testing/re.c	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/re.c	2008-06-05 08:33:02 UTC (rev 249)
@@ -2,7 +2,7 @@
 
   re.c -
 
-  $Author: matz $
+  $Author: mame $
   created at: Mon Aug  9 18:24:49 JST 1993
 
   Copyright (C) 1993-2007 Yukihiro Matsumoto
@@ -325,7 +325,9 @@
 static void
 rb_reg_expr_str(VALUE str, const char *s, long len)
 {
+#if !WITH_OBJC
     rb_encoding *enc = rb_enc_get(str);
+#endif
     const char *p, *pend;
     int need_escape = 0;
     int c, clen;
@@ -924,6 +926,14 @@
     rm->char_offset_updated = 1;
 }
 
+static void
+match_check(VALUE match)
+{
+    if (!RMATCH(match)->regexp) {
+	rb_raise(rb_eTypeError, "uninitialized Match");
+    }
+}
+
 /* :nodoc: */
 static VALUE
 match_init_copy(VALUE obj, VALUE orig)
@@ -939,9 +949,6 @@
     RMATCH(obj)->regexp = RMATCH(orig)->regexp;
 
     rm = RMATCH(obj)->rmatch;
-    onig_region_free(&rm->regs, 0);
-    rm->regs.allocated = 0;
-
     onig_region_copy(&rm->regs, RMATCH_REGS(orig));
 
     if (!RMATCH(orig)->rmatch->char_offset_updated) {
@@ -974,6 +981,7 @@
 static VALUE
 match_regexp(VALUE match)
 {
+    match_check(match);
     return RMATCH(match)->regexp;
 }
 
@@ -994,6 +1002,7 @@
 static VALUE
 match_names(VALUE match)
 {
+    match_check(match);
     return rb_reg_names(RMATCH(match)->regexp);
 }
 
@@ -1012,6 +1021,7 @@
 static VALUE
 match_size(VALUE match)
 {
+    match_check(match);
     return INT2FIX(RMATCH_REGS(match)->num_regs);
 }
 
@@ -1024,6 +1034,7 @@
     struct re_registers *regs = RMATCH_REGS(match);
     VALUE regexp = RMATCH(match)->regexp;
 
+    match_check(match);
     switch(TYPE(backref)) {
       default:
         return NUM2INT(backref);
@@ -1074,6 +1085,7 @@
     int i = match_backref_number(match, n);
     struct re_registers *regs = RMATCH_REGS(match);
 
+    match_check(match);
     if (i < 0 || regs->num_regs <= i)
 	rb_raise(rb_eIndexError, "index %d out of matches", i);
 
@@ -1109,6 +1121,7 @@
     int i = match_backref_number(match, n);
     struct re_registers *regs = RMATCH_REGS(match);
 
+    match_check(match);
     if (i < 0 || regs->num_regs <= i)
 	rb_raise(rb_eIndexError, "index %d out of matches", i);
 
@@ -1143,6 +1156,7 @@
     int i = match_backref_number(match, n);
     struct re_registers *regs = RMATCH_REGS(match);
 
+    match_check(match);
     if (i < 0 || regs->num_regs <= i)
 	rb_raise(rb_eIndexError, "index %d out of matches", i);
 
@@ -1203,7 +1217,7 @@
 rb_reg_preprocess(const char *p, const char *end, rb_encoding *enc,
         rb_encoding **fixed_enc, onig_errmsg_buffer err);
 
-
+#if !WITH_OBJC
 static void
 reg_enc_error(VALUE re, VALUE str)
 {
@@ -1212,6 +1226,7 @@
 	     rb_enc_name(rb_enc_get(re)),
 	     rb_enc_name(rb_enc_get(str)));
 }
+#endif
 
 static rb_encoding*
 rb_reg_prepare_enc(VALUE re, VALUE str, int warn)
@@ -1302,7 +1317,9 @@
 {
     int range;
     rb_encoding *enc;
+#if !WITH_OBJC
     UChar *p, *string;
+#endif
 
     enc = rb_reg_prepare_enc(re, str, 0);
 
@@ -1430,6 +1447,7 @@
 {
     struct re_registers *regs;
     if (NIL_P(match)) return Qnil;
+    match_check(match);
     regs = RMATCH_REGS(match);
     if (nth >= regs->num_regs) {
 	return Qnil;
@@ -1450,6 +1468,7 @@
     struct re_registers *regs;
 
     if (NIL_P(match)) return Qnil;
+    match_check(match);
     regs = RMATCH_REGS(match);
     if (nth >= regs->num_regs) {
 	return Qnil;
@@ -1492,6 +1511,7 @@
     struct re_registers *regs;
 
     if (NIL_P(match)) return Qnil;
+    match_check(match);
     regs = RMATCH_REGS(match);
     if (BEG(0) == -1) return Qnil;
     str = rb_str_subseq(RMATCH(match)->str, 0, BEG(0));
@@ -1519,6 +1539,7 @@
     struct re_registers *regs;
 
     if (NIL_P(match)) return Qnil;
+    match_check(match);
     regs = RMATCH_REGS(match);
     if (BEG(0) == -1) return Qnil;
     str = RMATCH(match)->str;
@@ -1535,6 +1556,7 @@
     struct re_registers *regs;
 
     if (NIL_P(match)) return Qnil;
+    match_check(match);
     regs = RMATCH_REGS(match);
     if (BEG(0) == -1) return Qnil;
 
@@ -1577,6 +1599,7 @@
     int i;
     int taint = OBJ_TAINTED(match);
 
+    match_check(match);
     for (i=start; i<regs->num_regs; i++) {
 	if (regs->beg[i] == -1) {
 	    rb_ary_push(ary, Qnil);
@@ -1645,18 +1668,18 @@
 static int
 name_to_backref_number(struct re_registers *regs, VALUE regexp, const char* name, const char* name_end)
 {
-  int num;
+    int num;
 
-  num = onig_name_to_backref_number(RREGEXP(regexp)->ptr,
-            (const unsigned char* )name, (const unsigned char* )name_end, regs);
-  if (num >= 1) {
-    return num;
-  }
-  else {
-    VALUE s = rb_str_new(name, (long )(name_end - name));
-    rb_raise(rb_eIndexError, "undefined group name reference: %s",
-                             StringValuePtr(s));
-  }
+    num = onig_name_to_backref_number(RREGEXP(regexp)->ptr,
+	(const unsigned char* )name, (const unsigned char* )name_end, regs);
+    if (num >= 1) {
+	return num;
+    }
+    else {
+	VALUE s = rb_str_new(name, (long )(name_end - name));
+	rb_raise(rb_eIndexError, "undefined group name reference: %s",
+				 StringValuePtr(s));
+    }
 }
 
 /*
@@ -1690,6 +1713,7 @@
 {
     VALUE idx, rest;
 
+    match_check(match);
     rb_scan_args(argc, argv, "11", &idx, &rest);
 
     if (NIL_P(rest)) {
@@ -1749,6 +1773,7 @@
 match_values_at(int argc, VALUE *argv, VALUE match)
 {
     struct re_registers *regs = RMATCH_REGS(match);
+    match_check(match);
     return rb_get_values_at(match, regs->num_regs, argc, argv, match_entry);
 }
 
@@ -1768,6 +1793,7 @@
 {
     VALUE str = rb_reg_last_match(match);
 
+    match_check(match);
     if (NIL_P(str)) str = rb_str_new(0,0);
     if (OBJ_TAINTED(match)) OBJ_TAINT(str);
     if (OBJ_TAINTED(RMATCH(match)->str)) OBJ_TAINT(str);
@@ -1788,6 +1814,7 @@
 static VALUE
 match_string(VALUE match)
 {
+    match_check(match);
     return RMATCH(match)->str;	/* str is frozen */
 }
 
@@ -1833,7 +1860,7 @@
 static VALUE
 match_inspect(VALUE match)
 {
-    char *cname = rb_obj_classname(match);
+    const char *cname = rb_obj_classname(match);
     VALUE str;
     int i;
     struct re_registers *regs = RMATCH_REGS(match);
@@ -1997,7 +2024,9 @@
     char *chbuf = ALLOCA_N(char, chmaxlen);
     int chlen = 0;
     int byte;
+#if !WITH_OBJC
     int l;
+#endif
 
     memset(chbuf, 0, chmaxlen);
 
@@ -2899,7 +2928,9 @@
 VALUE
 rb_reg_quote(VALUE str)
 {
+#if !WITH_OBJC
     rb_encoding *enc = rb_enc_get(str);
+#endif
     const char *s, *send;
     char *t;
     VALUE tmp;
@@ -3103,7 +3134,9 @@
     else {
 	int i;
 	VALUE source = rb_str_buf_new(0);
+#if !WITH_OBJC
 	rb_encoding *result_enc;
+#endif
 
         int has_asciionly = 0;
         rb_encoding *has_ascii_compat_fixed = 0;

Modified: MacRuby/branches/testing/regenc.h
===================================================================
--- MacRuby/branches/testing/regenc.h	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/regenc.h	2008-06-05 08:33:02 UTC (rev 249)
@@ -70,7 +70,7 @@
 #define ONIG_CHECK_NULL_RETURN(p)          if (ONIG_IS_NULL(p)) return NULL
 #define ONIG_CHECK_NULL_RETURN_VAL(p,val)  if (ONIG_IS_NULL(p)) return (val)
 
-#define enclen(enc,p,e)      ONIGENC_MBC_ENC_LEN(enc,p,e)
+#define enclen(enc,p,e) ((enc->max_enc_len == enc->min_enc_len) ? enc->min_enc_len : ONIGENC_MBC_ENC_LEN(enc,p,e))
 
 /* character types bit flag */
 #define BIT_CTYPE_NEWLINE  (1<< ONIGENC_CTYPE_NEWLINE)

Modified: MacRuby/branches/testing/regerror.c
===================================================================
--- MacRuby/branches/testing/regerror.c	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/regerror.c	2008-06-05 08:33:02 UTC (rev 249)
@@ -41,7 +41,7 @@
 extern UChar*
 onig_error_code_to_format(int code)
 {
-  char *p;
+  const char *p;
 
   if (code >= 0) return (UChar* )0;
 

Modified: MacRuby/branches/testing/regexec.c
===================================================================
--- MacRuby/branches/testing/regexec.c	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/regexec.c	2008-06-05 08:33:02 UTC (rev 249)
@@ -2741,16 +2741,25 @@
 
   s = (UChar* )text;
 
+  if (enc->max_enc_len == enc->min_enc_len) {
+    int n = enc->max_enc_len;
+
+    while (s < end) {
+      if (*s == *target) {
+	p = s + 1;
+	t = target + 1;
+	if (target_end == t || memcmp(t, p, target_end - t) == 0)
+	  return s;
+      }
+      s += n;
+    }
+    return (UChar*)NULL;
+  }
   while (s < end) {
     if (*s == *target) {
       p = s + 1;
       t = target + 1;
-      while (t < target_end) {
-	if (*t != *p++)
-	  break;
-	t++;
-      }
-      if (t == target_end)
+      if (target_end == t || memcmp(t, p, target_end - t) == 0)
 	return s;
     }
     s += enclen(enc, s, end);

Modified: MacRuby/branches/testing/ruby.c
===================================================================
--- MacRuby/branches/testing/ruby.c	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/ruby.c	2008-06-05 08:33:02 UTC (rev 249)
@@ -72,6 +72,11 @@
     disable_rubyopt,
 };
 
+#define DUMP_BIT(bit) (1U << dump_##bit)
+enum dump_flag_bits {
+    dump_insns,
+};
+
 struct cmdline_options {
     int sflag, xflag;
     int do_loop, do_print;
@@ -83,7 +88,8 @@
     unsigned int disable;
     int verbose;
     int yydebug;
-    char *script;
+    unsigned int dump;
+    const char *script;
     VALUE script_name;
     VALUE e_script;
     struct {
@@ -592,6 +598,14 @@
     rb_warn("unknown argument for --disable: `%.*s'", len, str);
 }
 
+static void
+dump_option(const char *str, int len, void *arg)
+{
+#define SET_WHEN_DUMP(bit) SET_WHEN(#bit, DUMP_BIT(bit), str, len)
+    SET_WHEN_DUMP(insns);
+    rb_warn("don't know how to dump `%.*s', (insns)", len, str);
+}
+
 static int
 proc_options(int argc, char **argv, struct cmdline_options *opt)
 {
@@ -879,6 +893,10 @@
 	    }
 	    else if (strcmp("yydebug", s) == 0)
 		opt->yydebug = 1;
+	    else if (strncmp("dump", s, n = 4) == 0 && (!s[n] || s[n] == '=')) {
+		if (!(s += n + 1)[-1] && (!--argc || !(s = *++argv)) && *s != '-') break;
+		ruby_each_words(s, dump_option, &opt->dump);
+	    }
 	    else if (strcmp("help", s) == 0) {
 		usage(origarg.argv[0]);
 		rb_exit(EXIT_SUCCESS);
@@ -971,6 +989,7 @@
     char **argv = argp->argv;
     NODE *tree = 0;
     VALUE parser;
+    VALUE iseq;
     rb_encoding *enc, *lenc;
     const char *s;
     char fbuf[MAXPATHLEN];
@@ -1168,8 +1187,16 @@
 	tree = rb_parser_while_loop(parser, tree, opt->do_line, opt->do_split);
     }
 
-    return rb_iseq_new(tree, rb_str_new2("<main>"),
+    iseq = rb_iseq_new(tree, rb_str_new2("<main>"),
 		       opt->script_name, Qfalse, ISEQ_TYPE_TOP);
+
+    if (opt->dump & DUMP_BIT(insns)) {
+	rb_io_write(rb_stdout, ruby_iseq_disasm(iseq));
+	rb_io_flush(rb_stdout);
+	return Qtrue;
+    }
+
+    return iseq;
 }
 
 static NODE *
@@ -1403,7 +1430,6 @@
 set_arg0(VALUE val, ID id)
 {
     const char *s;
-    char *t;
     long i;
 
     if (origarg.argv == 0)
@@ -1434,13 +1460,13 @@
     }
 
     memcpy(origarg.argv[0], s, i);
-    t = origarg.argv[0] + i;
-    *t = '\0';
 
-    if (i + 1 < origarg.len) memset(t + 1, ' ', origarg.len - i - 1);
-
     {
 	int j;
+	char *t = origarg.argv[0] + i;
+	*t = '\0';
+
+	if (i + 1 < origarg.len) memset(t + 1, ' ', origarg.len - i - 1);
 	for (j = 1; j < origarg.argc; j++) {
 	    origarg.argv[j] = t;
 	}

Modified: MacRuby/branches/testing/sample-macruby/CircleView/CircleView.rb
===================================================================
--- MacRuby/branches/testing/sample-macruby/CircleView/CircleView.rb	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/sample-macruby/CircleView/CircleView.rb	2008-06-05 08:33:02 UTC (rev 249)
@@ -159,12 +159,26 @@
     # We schedule a timer for a desired 30fps animation rate.
     # In performAnimation: we determine exactly
     # how much time has elapsed and animate accordingly.
+
+=begin
+    @timer = NSTimer.timerWithTimeInterval 1.0/30.0,
+      target:self,
+      selector:'performAnimation:',
+      userInfo:nil,
+      repeats:true
+=end
+    
+    #@timer = Foo.foo(self)
+    
+#=begin
     @timer = NSTimer.scheduledTimerWithTimeInterval 1.0/30.0, 
       target:self,
       selector:'performAnimation:',
       userInfo:nil,
       repeats:true
-      
+#=end
+ p @timer
+           
     # The next two lines make sure that animation will continue to occur
     # while modal panels are displayed and while event tracking is taking
     # place (for example, while a slider is being dragged).

Modified: MacRuby/branches/testing/sample-macruby/CircleView/main.m
===================================================================
--- MacRuby/branches/testing/sample-macruby/CircleView/main.m	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/sample-macruby/CircleView/main.m	2008-06-05 08:33:02 UTC (rev 249)
@@ -8,6 +8,16 @@
 
 #import <MacRuby/MacRuby.h>
 
+#import <Cocoa/Cocoa.h>
+ at interface Foo
+ at end
+ at implementation Foo
++(id)foo:(id)rcv
+{
+  return [NSTimer scheduledTimerWithTimeInterval:1.0/30.0 target:rcv selector:@selector(performAnimation:) userInfo:nil repeats:true];
+}
+ at end
+
 int main(int argc, char *argv[])
 {
     return macruby_main("rb_main.rb", argc, argv);

Copied: MacRuby/branches/testing/sample-macruby/Scripts/circle.rb (from rev 248, MacRuby/trunk/sample-macruby/Scripts/circle.rb)
===================================================================
--- MacRuby/branches/testing/sample-macruby/Scripts/circle.rb	                        (rev 0)
+++ MacRuby/branches/testing/sample-macruby/Scripts/circle.rb	2008-06-05 08:33:02 UTC (rev 249)
@@ -0,0 +1,15 @@
+# Create a new PDF file and draw a red circle in it, using Core Graphics.
+framework 'Cocoa'
+
+url = NSURL.fileURLWithPath('circle.pdf')
+pdf = CGPDFContextCreateWithURL(url, [[0, 0], [617, 792]], nil)
+
+CGPDFContextBeginPage(pdf, nil)
+CGContextSetRGBFillColor(pdf, 1.0, 0.0, 0.0, 1.0)
+CGContextAddArc(pdf, 300, 300, 100, 0, 2 * Math::PI, 1)
+CGContextFillPath(pdf)
+CGPDFContextEndPage(pdf)
+CGContextFlush(pdf)
+
+# CGContextRef is a resourceful object, so it must be released manually.
+CFRelease(pdf)

Modified: MacRuby/branches/testing/sample-macruby/Scripts/hello_world.rb
===================================================================
--- MacRuby/branches/testing/sample-macruby/Scripts/hello_world.rb	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/sample-macruby/Scripts/hello_world.rb	2008-06-05 08:33:02 UTC (rev 249)
@@ -11,7 +11,7 @@
 end
 
 app = NSApplication.sharedApplication
-app.delegate = AppDelegate.alloc.init
+app.delegate = AppDelegate.new
 
 win = NSWindow.alloc.initWithContentRect([200, 300, 250, 100],
     styleMask:NSTitledWindowMask|NSClosableWindowMask|NSMiniaturizableWindowMask|NSResizableWindowMask, 

Modified: MacRuby/branches/testing/signal.c
===================================================================
--- MacRuby/branches/testing/signal.c	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/signal.c	2008-06-05 08:33:02 UTC (rev 249)
@@ -2,7 +2,7 @@
 
   signal.c -
 
-  $Author: nobu $
+  $Author: mame $
   created at: Tue Dec 20 10:13:44 JST 1994
 
   Copyright (C) 1993-2007 Yukihiro Matsumoto
@@ -222,6 +222,7 @@
     if (argc > 0) {
 	sig = rb_check_to_integer(argv[0], "to_int");
 	if (!NIL_P(sig)) argnum = 2;
+	else sig = argv[0];
     }
     if (argc < 1 || argnum < argc) {
 	rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)",
@@ -252,9 +253,7 @@
 	if (!signo) {
 	    rb_raise(rb_eArgError, "unsupported name `SIG%s'", signm);
 	}
-	if (SYMBOL_P(sig)) {
-	    sig = rb_str_new2(signm);
-	}
+	sig = rb_sprintf("SIG%s", signm);
     }
     rb_call_super(1, &sig);
     rb_iv_set(self, "signo", INT2NUM(signo));
@@ -262,7 +261,20 @@
     return self;
 }
 
+/*
+ * call-seq:
+ *    signal_exception.signo   =>  num
+ *
+ *  Returns a signal number.
+ */
+
 static VALUE
+esignal_signo(VALUE self)
+{
+    return rb_iv_get(self, "signo");
+}
+
+static VALUE
 interrupt_init(int argc, VALUE *argv, VALUE self)
 {
     VALUE args[2];
@@ -1069,7 +1081,7 @@
     rb_define_module_function(mSignal, "list", sig_list, 0);
 
     rb_define_method(rb_eSignal, "initialize", esignal_init, -1);
-    rb_attr(rb_eSignal, rb_intern("signo"), 1, 0, 0);
+    rb_define_method(rb_eSignal, "signo", esignal_signo, 0);
     rb_alias(rb_eSignal, rb_intern("signm"), rb_intern("message"));
     rb_define_method(rb_eInterrupt, "initialize", interrupt_init, -1);
 

Modified: MacRuby/branches/testing/sprintf.c
===================================================================
--- MacRuby/branches/testing/sprintf.c	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/sprintf.c	2008-06-05 08:33:02 UTC (rev 249)
@@ -21,6 +21,7 @@
 #define BITSPERDIG (SIZEOF_BDIGITS*CHAR_BIT)
 #define EXTENDSIGN(n, l) (((~0 << (n)) >> (((n)*(l)) % BITSPERDIG)) & ~(~0 << (n)))
 
+#if !WITH_OBJC
 static void fmt_setup(char*,int,int,int,int);
 
 static char*
@@ -67,6 +68,7 @@
     }
     return c;
 }
+#endif
 
 #define FNONE  0
 #define FSHARP 1
@@ -987,7 +989,6 @@
     if (tainted) OBJ_TAINT(result);
     return result;
 }
-#endif
 
 static void
 fmt_setup(char *buf, int c, int flags, int width, int prec)
@@ -1058,6 +1059,7 @@
     fp->_p = (unsigned char *)buf;
     return 0;
 }
+#endif
 
 VALUE
 rb_enc_vsprintf(rb_encoding *enc, const char *fmt, va_list ap)

Modified: MacRuby/branches/testing/string.c
===================================================================
--- MacRuby/branches/testing/string.c	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/string.c	2008-06-05 08:33:02 UTC (rev 249)
@@ -2,7 +2,7 @@
 
   string.c -
 
-  $Author: mame $
+  $Author: nobu $
   created at: Mon Aug  9 17:12:58 JST 1993
 
   Copyright (C) 1993-2007 Yukihiro Matsumoto
@@ -181,7 +181,6 @@
 	CFIndex datalen;
 	const UInt8 *dataptr;
 	CFStringRef bytestr;
-	const char *strptr;
 
 	data = (CFDataRef)cfdata;
 	datalen = CFDataGetLength(data);
@@ -921,7 +920,7 @@
 {
     VALUE orig;
 
-    if (rb_scan_args(argc, argv, "01", &orig) == 1)
+    if (argc > 0 && rb_scan_args(argc, argv, "01", &orig) == 1)
 	rb_str_replace(str, orig);
     return str;
 }
@@ -1109,7 +1108,7 @@
 static VALUE
 rb_str_empty(VALUE str)
 {
-    if (CFStringGetLength((CFStringRef)str) == 0)
+    if (RSTRING_CLEN(str) == 0)
 	return Qtrue;
     return Qfalse;
 }
@@ -2185,10 +2184,13 @@
     if (FIXNUM_P(str2)) {
 #if WITH_OBJC
         int c = FIX2INT(str2);
+	char buf[2];
 
 	rb_str_modify(str1);
-        CFStringAppendCharacters((CFMutableStringRef)str1, (const UniChar *)&c, 
-	    1);
+	buf[0] = (char)c;
+	buf[1] = '\0';
+	CFStringAppendCString((CFMutableStringRef)str1, buf, 
+			      kCFStringEncodingUTF8);
 	rb_gc_malloc_increase(sizeof(UniChar));
 #else
 	rb_encoding *enc = STR_ENC_GET(str1);
@@ -3042,13 +3044,10 @@
   NEIGHBOR_NOT_CHAR is returned if invalid character or the range has only one
   character.
  */
+#if !WITH_OBJC
 static enum neighbor_char
 enc_succ_alnum_char(char *p, int len, rb_encoding *enc, char *carry)
 {
-#if WITH_OBJC
-    /* TODO rewrite me */
-    return NEIGHBOR_NOT_CHAR;
-#else
     enum neighbor_char ret;
     int c;
     int ctype;
@@ -3100,10 +3099,9 @@
     MEMCPY(carry, p, char, len);
     enc_succ_char(carry, len, enc);
     return NEIGHBOR_WRAPPED;
+}
 #endif
-}
 
-
 /*
  *  call-seq:
  *     str.succ   => new_str
@@ -3316,10 +3314,13 @@
     VALUE current, after_end;
     ID succ;
     int n, excl;
+#if !WITH_OBJC
     rb_encoding *enc;
+#endif
 
     rb_scan_args(argc, argv, "11", &end, &exclusive);
     excl = RTEST(exclusive);
+    succ = rb_intern("succ");
     StringValue(end);
 #if WITH_OBJC
     if (RSTRING_CLEN(beg) == 1 && RSTRING_CLEN(end) == 1) {
@@ -3361,7 +3362,6 @@
     n = rb_str_cmp(beg, end);
     if (n > 0 || (excl && n == 0)) return beg;
 	
-    succ = rb_intern("succ");
     after_end = rb_funcall(end, succ, 0, 0);
     current = beg;
     while (!rb_str_equal(current, after_end)) {
@@ -3586,7 +3586,9 @@
 {
     VALUE match;
     long start, end, len;
+#if !WITH_OBJC
     rb_encoding *enc;
+#endif
     struct re_registers *regs;
 
     if (rb_reg_search(re, str, 0, 0) < 0) {
@@ -3821,7 +3823,6 @@
     struct re_registers *regs;
     int iter = 0;
     int tainted = 0;
-    long plen;
 
     if (argc == 1 && rb_block_given_p()) {
 	iter = 1;
@@ -3840,8 +3841,8 @@
 
     pat = get_pat(argv[0], 1);
     if (rb_reg_search(pat, str, 0, 0) >= 0) {
+#if !WITH_OBJC
 	rb_encoding *enc;
-#if !WITH_OBJC
 	int cr = ENC_CODERANGE(str);
 #endif
 
@@ -3891,6 +3892,7 @@
 	if (OBJ_TAINTED(repl)) tainted = 1;
 #else
 	rb_enc_associate(str, enc);
+	if (OBJ_TAINTED(repl)) tainted = 1;
 	if (ENC_CODERANGE_UNKNOWN < cr && cr < ENC_CODERANGE_BROKEN) {
 	    int cr2 = ENC_CODERANGE(repl);
 	    if (cr2 == ENC_CODERANGE_UNKNOWN || cr2 > cr) cr = cr2;
@@ -3963,7 +3965,7 @@
     VALUE pat, val, repl, match, dest, hash = Qnil;
     struct re_registers *regs;
     long beg, n;
-    long offset, blen, slen, len;
+    long offset, slen, len;
     int iter = 0;
     const char *sp, *cp;
     int tainted = 0;
@@ -3999,6 +4001,7 @@
     slen = RSTRING_CLEN(str);
     sp = RSTRING_CPTR(str);
     cp = sp;
+    str_enc = NULL;
 #else
     blen = RSTRING_LEN(str) + 30; /* len + margin */
     dest = rb_str_buf_new(blen);
@@ -4066,6 +4069,7 @@
     rb_backref_set(match);
 #if WITH_OBJC
     if (bang) {
+	rb_str_modify(str);
 	RSTRING_SYNC(str);
 	RSTRING_SYNC(dest);
 	CFStringReplaceAll((CFMutableStringRef)str, (CFStringRef)dest);
@@ -4162,7 +4166,6 @@
 VALUE
 rb_str_replace(VALUE str, VALUE str2)
 {
-    long len;
     if (str == str2) return str;
 #if WITH_OBJC
     rb_str_modify(str);
@@ -4517,8 +4520,10 @@
 str_cat_char(VALUE str, int c, rb_encoding *enc)
 {
 #if WITH_OBJC
-    CFStringAppendCharacters((CFMutableStringRef)str, 
-	(const UniChar *)&c, 1); 	 
+    char buf[2];
+    buf[0] = (char)c;
+    buf[1] = '\0';
+    CFStringAppendCString((CFMutableStringRef)str, buf, kCFStringEncodingUTF8);
 #else
     char s[16];
     int n = rb_enc_codelen(c, enc);
@@ -4640,7 +4645,9 @@
 	    char *s;
             const char *q;
 
+#if !WITH_OBJC
 	  escape_codepoint:
+#endif
             for (q = p-n; q < p; q++) {
                 s = buf;
                 sprintf(buf, "\\x%02X", *q & 0377);
@@ -4949,7 +4956,6 @@
     CFStringRef tmp;
     long i, n;
     bool changed;
-    UniChar c;
     UniChar *buffer;
 
     rb_str_modify(str);
@@ -5182,7 +5188,6 @@
 {
     int i;
     long n;
-    bool changed;
     CFMutableCharacterSetRef charset;
     CFRange search_range, result_range; 
 
@@ -5410,12 +5415,13 @@
 	else {
 	    /* TODO: support all syntaxes */
 	    char sb, se, rb, re;
-	    long n;
 	    bool s_is_range, r_is_range;
 	    CFStringRef substr;
 	    bool release_substr;
 	    long delta;
 
+	    sb = se = rb = re = 0;
+
 	    if (_ctx->src_len == 3 && _ctx->src[1] == '-') {
 		sb = _ctx->src[0];
 		se = _ctx->src[2];
@@ -6218,7 +6224,6 @@
     long beg, end, i = 0;
     int lim = 0;
     VALUE result, tmp;
-    const char *cstr;
     long clen;
 
 #if !WITH_OBJC
@@ -6288,7 +6293,7 @@
 #if WITH_OBJC
     if (awk_split || spat_string) {
 	CFRange search_range;
-	CFCharacterSetRef charset;
+	CFCharacterSetRef charset = NULL;
 	if (spat == Qnil)
 	    charset = CFCharacterSetGetPredefined(
 		kCFCharacterSetWhitespaceAndNewline);
@@ -6519,7 +6524,6 @@
 {
 #if WITH_OBJC
     VALUE rs;
-    CFArrayRef ranges;
     long n;
     CFStringRef substr;
     CFRange sub_range, search_range, res_range;
@@ -6947,7 +6951,7 @@
 	if (len == 0) return Qnil;
 	p = RSTRING_PTR(str);
     e = p + len;
-    if (rb_scan_args(argc, argv, "01", &rs) == 0) {
+    if (argc == 0) {
 	rs = rb_rs;
 	if (rs == rb_default_rs) {
 	  smart_chomp:
@@ -7286,7 +7290,9 @@
 static VALUE
 scan_once(VALUE str, VALUE pat, long *start, long strlen, bool pat_is_string)
 {
+#if !WITH_OBJC
     rb_encoding *enc;
+#endif
     VALUE result, match;
     struct re_registers *regs;
     long i;
@@ -7302,11 +7308,11 @@
 	    CFRangeMake(*start, strlen - *start),
 	    0,
 	    &result_range)) {
-	    CFStringRef str = CFStringCreateWithSubstring(NULL, 
+	    CFStringRef substr = CFStringCreateWithSubstring(NULL, 
 		(CFStringRef)str, result_range);
 	    *start = result_range.location + result_range.length + 1;
-	    result = (VALUE)CFStringCreateMutableCopy(NULL, 0, str);
-	    CFRelease(str);
+	    result = (VALUE)CFStringCreateMutableCopy(NULL, 0, substr);
+	    CFRelease(substr);
 	    CFMakeCollectable((CFTypeRef)result);
 	}
 	else {
@@ -7838,7 +7844,7 @@
 {
     long pos;
     int regex = Qfalse;
-    long strlen, seplen;
+    long strlen, seplen = 0;
 
     if (TYPE(sep) == T_REGEXP) {
 	pos = rb_reg_search(sep, str, 0, 0);
@@ -7959,8 +7965,10 @@
 rb_str_end_with(int argc, VALUE *argv, VALUE str)
 {
     int i;
+#if !WITH_OBJC
     char *p, *s;
     rb_encoding *enc;
+#endif
 
     for (i=0; i<argc; i++) {
 	VALUE tmp = rb_check_string_type(argv[i]);
@@ -8073,6 +8081,37 @@
 #endif
 }
 
+#if WITH_OBJC
+static VALUE
+rb_str_transform_bang(VALUE str, VALUE transform_name)
+{
+    CFRange range;
+
+    rb_str_modify(str);
+    StringValue(transform_name);
+    
+    range = CFRangeMake(0, RSTRING_CLEN(str));
+
+    if (!CFStringTransform((CFMutableStringRef)str, 
+	&range,
+	(CFStringRef)transform_name,
+       	false))
+	rb_raise(rb_eRuntimeError, "cannot apply transformation `%s' to `%s'",
+		RSTRING_CPTR(transform_name), RSTRING_CPTR(str));
+
+    return range.length == kCFNotFound ? Qnil : str;
+}
+
+static VALUE
+rb_str_transform(VALUE str, VALUE transform_name)
+{
+    str = rb_str_dup(str);
+    rb_str_transform_bang(str, transform_name);
+    return str;
+}
+
+#endif
+
 /**********************************************************************
  * Document-class: Symbol
  *
@@ -8503,8 +8542,7 @@
     rb_define_method(rb_cString, "==", rb_str_equal, 1);
     rb_define_method(rb_cString, "eql?", rb_str_eql, 1);
 #if 1 
-/* FIXME remove me once we use the objc dispatch for everything
-/*#if !WITH_OBJC*/
+    /* FIXME remove me once we use the objc dispatch for everything */
     rb_define_method(rb_cString, "hash", rb_str_hash_m, 0);
 #endif
     rb_define_method(rb_cString, "casecmp", rb_str_casecmp, 1);
@@ -8624,6 +8662,11 @@
     rb_define_method(rb_cString, "valid_encoding?", rb_str_valid_encoding_p, 0);
     rb_define_method(rb_cString, "ascii_only?", rb_str_is_ascii_only_p, 0);
 
+#if WITH_OBJC
+    rb_define_method(rb_cString, "transform", rb_str_transform, 1);
+    rb_define_method(rb_cString, "transform!", rb_str_transform_bang, 1);
+#endif
+
     id_to_s = rb_intern("to_s");
 
     rb_fs = Qnil;

Modified: MacRuby/branches/testing/struct.c
===================================================================
--- MacRuby/branches/testing/struct.c	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/struct.c	2008-06-05 08:33:02 UTC (rev 249)
@@ -2,7 +2,7 @@
 
   struct.c -
 
-  $Author: matz $
+  $Author: nobu $
   created at: Tue Mar 22 18:44:30 JST 1995
 
   Copyright (C) 1993-2007 Yukihiro Matsumoto
@@ -227,7 +227,7 @@
 }
 
 VALUE
-rb_struct_define_without_accessor(char *class_name, VALUE super, rb_alloc_func_t alloc, ...)
+rb_struct_define_without_accessor(const char *class_name, VALUE super, rb_alloc_func_t alloc, ...)
 {
     VALUE klass;
     va_list ar;
@@ -483,7 +483,7 @@
 static VALUE
 inspect_struct(VALUE s, VALUE dummy, int recur)
 {
-    char *cname = rb_class2name(rb_obj_class(s));
+    const char *cname = rb_class2name(rb_obj_class(s));
     VALUE str, members;
     long i;
 

Modified: MacRuby/branches/testing/template/insns.inc.tmpl
===================================================================
--- MacRuby/branches/testing/template/insns.inc.tmpl	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/template/insns.inc.tmpl	2008-06-05 08:33:02 UTC (rev 249)
@@ -19,4 +19,3 @@
 
 #define VM_INSTRUCTION_SIZE <%= @insns.size %>
 
-

Modified: MacRuby/branches/testing/test/erb/test_erb.rb
===================================================================
--- MacRuby/branches/testing/test/erb/test_erb.rb	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/test/erb/test_erb.rb	2008-06-05 08:33:02 UTC (rev 249)
@@ -54,16 +54,16 @@
 
   def _test_core(safe)
     erb = @erb.new("hello")
-    assert_equal(erb.result, "hello")
+    assert_equal("hello", erb.result)
 
     erb = @erb.new("hello", safe, 0)
-    assert_equal(erb.result, "hello")
+    assert_equal("hello", erb.result)
 
     erb = @erb.new("hello", safe, 1)
-    assert_equal(erb.result, "hello")
+    assert_equal("hello", erb.result)
 
     erb = @erb.new("hello", safe, 2)
-    assert_equal(erb.result, "hello")
+    assert_equal("hello", erb.result)
 
     src = <<EOS
 %% hi
@@ -159,7 +159,7 @@
 
   def test_safe_04
     erb = @erb.new('<%=$SAFE%>', 4)
-    assert_equal(erb.result(TOPLEVEL_BINDING.taint), '4')
+    assert_equal('4', erb.result(TOPLEVEL_BINDING.taint))
   end
 
   class Foo; end

Modified: MacRuby/branches/testing/test/net/imap/test_imap.rb
===================================================================
--- MacRuby/branches/testing/test/net/imap/test_imap.rb	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/test/net/imap/test_imap.rb	2008-06-05 08:33:02 UTC (rev 249)
@@ -81,6 +81,37 @@
     end
   end
 
+  def test_unexpected_eof
+    server = TCPServer.new(0)
+    port = server.addr[1]
+    Thread.start do
+      begin
+        sock = server.accept
+        begin
+          sock.print("* OK test server\r\n")
+          sock.gets
+#          sock.print("* BYE terminating connection\r\n")
+#          sock.print("RUBY0001 OK LOGOUT completed\r\n")
+        ensure
+          sock.close
+        end
+      rescue
+      end
+    end
+    begin
+      begin
+        imap = Net::IMAP.new("localhost", :port => port)
+        assert_raise(EOFError) do
+          imap.logout
+        end
+      ensure
+        imap.disconnect if imap
+      end
+    ensure
+      server.close
+    end
+  end
+
   private
 
   def imaps_test

Modified: MacRuby/branches/testing/test/ruby/envutil.rb
===================================================================
--- MacRuby/branches/testing/test/ruby/envutil.rb	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/test/ruby/envutil.rb	2008-06-05 08:33:02 UTC (rev 249)
@@ -34,11 +34,6 @@
 
   LANG_ENVS = %w"LANG LC_ALL LC_CTYPE"
   def rubyexec(*args)
-    if /(mswin|bccwin|mingw|emx)/ =~ RUBY_PLATFORM
-      flunk("cannot test in win32")
-      return
-    end
-
     ruby = EnvUtil.rubybin
     c = "C"
     env = {}
@@ -77,9 +72,16 @@
     module Assertions
       public
       def assert_normal_exit(testsrc, message = '')
-        IO.popen([EnvUtil.rubybin, '-W0'], 'w') {|io|
-          io.write testsrc
-        }
+        in_c, in_p = IO.pipe
+        out_p, out_c = IO.pipe
+        pid = spawn(EnvUtil.rubybin, '-W0', STDIN=>in_c, STDOUT=>out_c, STDERR=>out_c)
+        in_c.close
+        out_c.close
+        in_p.write testsrc
+        in_p.close
+        msg = out_p.read
+        out_p.close
+        Process.wait pid
         status = $?
         faildesc = nil
         if status.signaled?
@@ -89,9 +91,27 @@
           if signame
             sigdesc = "SIG#{signame} (#{sigdesc})"
           end
-          full_message = build_message(message, "killed by ?", sigdesc)
+          if status.coredump?
+            sigdesc << " (core dumped)"
+          end
+          if msg.empty?
+            full_message = build_message(message, "pid ? killed by ?",
+                                         pid,
+                                         AssertionMessage::Literal.new(sigdesc))
+          else
+            msg << "\n" if /\n\z/ !~ msg
+            full_message = build_message(message, "pid ? killed by ?\n?",
+                                         pid,
+                                         AssertionMessage::Literal.new(sigdesc),
+                                         AssertionMessage::Literal.new(msg.gsub(/^/, '| ')))
+          end
         end
         assert_block(full_message) { !status.signaled? }
+      ensure
+        in_c.close if in_c && !in_c.closed?
+        in_p.close if in_p && !in_p.closed?
+        out_c.close if out_c && !out_c.closed?
+        out_p.close if out_p && !out_p.closed?
       end
     end
   end

Copied: MacRuby/branches/testing/test/ruby/test_argf.rb (from rev 248, MacRuby/trunk/test/ruby/test_argf.rb)
===================================================================
--- MacRuby/branches/testing/test/ruby/test_argf.rb	                        (rev 0)
+++ MacRuby/branches/testing/test/ruby/test_argf.rb	2008-06-05 08:33:02 UTC (rev 249)
@@ -0,0 +1,695 @@
+require 'test/unit'
+require 'timeout'
+require 'tmpdir'
+require 'tempfile'
+require_relative 'envutil'
+
+class TestArgf < Test::Unit::TestCase
+  def setup
+    @t1 = Tempfile.new("foo")
+    @t1.puts "1"
+    @t1.puts "2"
+    @t1.close
+    @t2 = Tempfile.new("bar")
+    @t2.puts "3"
+    @t2.puts "4"
+    @t2.close
+    @t3 = Tempfile.new("baz")
+    @t3.puts "5"
+    @t3.puts "6"
+    @t3.close
+    @tmps = [@t1, @t2, @t3]
+  end
+
+  def teardown
+    @tmps.each {|t|
+      bak = t.path + ".bak"
+      File.unlink bak if File.file? bak
+    }
+  end
+
+  def make_tempfile
+    t = Tempfile.new("foo")
+    t.puts "foo"
+    t.puts "bar"
+    t.puts "baz"
+    t.close
+    @tmps << t
+    t
+  end
+
+  def ruby(*args)
+    args = ['-e', '$>.write($<.read)'] if args.empty?
+    ruby = EnvUtil.rubybin
+    f = IO.popen([ruby] + args, 'r+')
+    yield(f)
+  ensure
+    f.close unless !f || f.closed?
+  end
+
+  def test_argf
+    ruby('-e', <<-SRC, @t1.path, @t2.path, @t3.path) do |f|
+      a = ARGF
+      b = a.dup
+      p [a.gets.chomp, a.lineno, b.gets.chomp, b.lineno] #=> ["1", 1, "1", 1]
+      p [a.gets.chomp, a.lineno, b.gets.chomp, b.lineno] #=> ["2", 2, "2", 2]
+      a.rewind
+      b.rewind
+      p [a.gets.chomp, a.lineno, b.gets.chomp, b.lineno] #=> ["1", 1, "1", 3]
+      p [a.gets.chomp, a.lineno, b.gets.chomp, b.lineno] #=> ["2", 2, "2", 4]
+      p [a.gets.chomp, a.lineno, b.gets.chomp, b.lineno] #=> ["3", 3, "3", 5]
+      p [a.gets.chomp, a.lineno, b.gets.chomp, b.lineno] #=> ["4", 4, "4", 6]
+      p [a.gets.chomp, a.lineno, b.gets.chomp, b.lineno] #=> ["5", 5, "5", 7]
+      a.rewind
+      b.rewind
+      p [a.gets.chomp, a.lineno, b.gets.chomp, b.lineno] #=> ["5", 5, "5", 8]
+      p [a.gets.chomp, a.lineno, b.gets.chomp, b.lineno] #=> ["6", 6, "6", 9]
+    SRC
+      a = f.read.split("\n")
+      assert_equal('["1", 1, "1", 1]', a.shift)
+      assert_equal('["2", 2, "2", 2]', a.shift)
+      assert_equal('["1", 1, "1", 3]', a.shift)
+      assert_equal('["2", 2, "2", 4]', a.shift)
+      assert_equal('["3", 3, "3", 5]', a.shift)
+      assert_equal('["4", 4, "4", 6]', a.shift)
+      assert_equal('["5", 5, "5", 7]', a.shift)
+      assert_equal('["5", 5, "5", 8]', a.shift)
+      assert_equal('["6", 6, "6", 9]', a.shift)
+
+      # is this test OK? [ruby-dev:34445]
+    end
+  end
+
+  def test_lineno
+    ruby('-e', <<-SRC, @t1.path, @t2.path, @t3.path) do |f|
+      a = ARGF
+      a.gets; p $.  #=> 1
+      a.gets; p $.  #=> 2
+      a.gets; p $.  #=> 3
+      a.rewind; p $.  #=> 3
+      a.gets; p $.  #=> 3
+      a.gets; p $.  #=> 4
+      a.rewind; p $.  #=> 4
+      a.gets; p $.  #=> 3
+      a.lineno = 1000; p $.  #=> 1000
+      a.gets; p $.  #=> 1001
+      a.gets; p $.  #=> 1002
+      $. = 2000
+      a.gets; p $.  #=> 2001
+      a.gets; p $.  #=> 2001
+    SRC
+      assert_equal("1,2,3,3,3,4,4,3,1000,1001,1002,2001,2001", f.read.chomp.gsub("\n", ","))
+    end
+  end
+
+  def test_lineno2
+    ruby('-e', <<-SRC, @t1.path, @t2.path, @t3.path) do |f|
+      a = ARGF.dup
+      a.gets; p $.  #=> 1
+      a.gets; p $.  #=> 2
+      a.gets; p $.  #=> 1
+      a.rewind; p $.  #=> 1
+      a.gets; p $.  #=> 1
+      a.gets; p $.  #=> 2
+      a.gets; p $.  #=> 1
+      a.lineno = 1000; p $.  #=> 1
+      a.gets; p $.  #=> 2
+      a.gets; p $.  #=> 2
+      $. = 2000
+      a.gets; p $.  #=> 2001
+      a.gets; p $.  #=> 2000
+    SRC
+      assert_equal("1,2,1,1,1,2,1,1,2,2,2000,2000", f.read.chomp.gsub("\n", ","))
+    end
+  end
+
+  def test_inplace
+    EnvUtil.rubyexec("-", @t1.path, @t2.path, @t3.path) do |w, r, e|
+      w.puts "ARGF.inplace_mode = '.bak'"
+      w.puts "while line = ARGF.gets"
+      w.puts "  puts line.chomp + '.new'"
+      w.puts "end"
+      w.close
+      assert_equal("", e.read)
+      assert_equal("", r.read)
+      assert_equal("1.new\n2.new\n", File.read(@t1.path))
+      assert_equal("3.new\n4.new\n", File.read(@t2.path))
+      assert_equal("5.new\n6.new\n", File.read(@t3.path))
+      assert_equal("1\n2\n", File.read(@t1.path + ".bak"))
+      assert_equal("3\n4\n", File.read(@t2.path + ".bak"))
+      assert_equal("5\n6\n", File.read(@t3.path + ".bak"))
+    end
+  end
+
+  def test_inplace2
+    EnvUtil.rubyexec("-", @t1.path, @t2.path, @t3.path) do |w, r, e|
+      w.puts "ARGF.inplace_mode = '.bak'"
+      w.puts "puts ARGF.gets.chomp + '.new'"
+      w.puts "puts ARGF.gets.chomp + '.new'"
+      w.puts "p ARGF.inplace_mode"
+      w.puts "ARGF.inplace_mode = nil"
+      w.puts "puts ARGF.gets.chomp + '.new'"
+      w.puts "puts ARGF.gets.chomp + '.new'"
+      w.puts "p ARGF.inplace_mode"
+      w.puts "ARGF.inplace_mode = '.bak'"
+      w.puts "puts ARGF.gets.chomp + '.new'"
+      w.puts "p ARGF.inplace_mode"
+      w.puts "ARGF.inplace_mode = nil"
+      w.puts "puts ARGF.gets.chomp + '.new'"
+      w.close
+      assert_equal("", e.read)
+      assert_equal("", r.read)
+      assert_equal("1.new\n2.new\n\".bak\"\n3.new\n4.new\nnil\n", File.read(@t1.path))
+      assert_equal("3\n4\n", File.read(@t2.path))
+      assert_equal("5.new\n\".bak\"\n6.new\n", File.read(@t3.path))
+      assert_equal("1\n2\n", File.read(@t1.path + ".bak"))
+      assert_equal(false, File.file?(@t2.path + ".bak"))
+      assert_equal("5\n6\n", File.read(@t3.path + ".bak"))
+    end
+  end
+
+  def test_inplace3
+    EnvUtil.rubyexec("-i.bak", "-", @t1.path, @t2.path, @t3.path) do |w, r, e|
+      w.puts "puts ARGF.gets.chomp + '.new'"
+      w.puts "puts ARGF.gets.chomp + '.new'"
+      w.puts "p $-i"
+      w.puts "$-i = nil"
+      w.puts "puts ARGF.gets.chomp + '.new'"
+      w.puts "puts ARGF.gets.chomp + '.new'"
+      w.puts "p $-i"
+      w.puts "$-i = '.bak'"
+      w.puts "puts ARGF.gets.chomp + '.new'"
+      w.puts "p $-i"
+      w.puts "$-i = nil"
+      w.puts "puts ARGF.gets.chomp + '.new'"
+      w.close
+      assert_equal("", e.read)
+      assert_equal("", r.read)
+      assert_equal("1.new\n2.new\n\".bak\"\n3.new\n4.new\nnil\n", File.read(@t1.path))
+      assert_equal("3\n4\n", File.read(@t2.path))
+      assert_equal("5.new\n\".bak\"\n6.new\n", File.read(@t3.path))
+      assert_equal("1\n2\n", File.read(@t1.path + ".bak"))
+      assert_equal(false, File.file?(@t2.path + ".bak"))
+      assert_equal("5\n6\n", File.read(@t3.path + ".bak"))
+    end
+  end
+
+  def test_inplace_rename_impossible
+    t = make_tempfile
+
+    EnvUtil.rubyexec("-", t.path) do |w, r, e|
+      w.puts "ARGF.inplace_mode = '/\\\\'"
+      w.puts "while line = ARGF.gets"
+      w.puts "  puts line.chomp + '.new'"
+      w.puts "end"
+      w.close
+      assert_match(/Can't rename .* to .*: .*. skipping file/, e.read)
+      assert_equal("", r.read)
+      assert_equal("foo\nbar\nbaz\n", File.read(t.path))
+    end
+  end
+
+  def test_inplace_no_backup
+    t = make_tempfile
+
+    EnvUtil.rubyexec("-", t.path) do |w, r, e|
+      w.puts "ARGF.inplace_mode = ''"
+      w.puts "while line = ARGF.gets"
+      w.puts "  puts line.chomp + '.new'"
+      w.puts "end"
+      w.close
+      assert_equal("", e.read)
+      assert_equal("", r.read)
+      assert_equal("foo.new\nbar.new\nbaz.new\n", File.read(t.path))
+    end
+  end
+
+  def test_inplace_dup
+    t = make_tempfile
+
+    EnvUtil.rubyexec("-", t.path) do |w, r, e|
+      w.puts "ARGF.inplace_mode = '.bak'"
+      w.puts "f = ARGF.dup"
+      w.puts "while line = f.gets"
+      w.puts "  puts line.chomp + '.new'"
+      w.puts "end"
+      w.close
+      assert_equal("", e.read)
+      assert_equal("", r.read)
+      assert_equal("foo.new\nbar.new\nbaz.new\n", File.read(t.path))
+    end
+  end
+
+  def test_inplace_stdin
+    t = make_tempfile
+
+    EnvUtil.rubyexec("-", "-") do |w, r, e|
+      w.puts "ARGF.inplace_mode = '.bak'"
+      w.puts "f = ARGF.dup"
+      w.puts "while line = f.gets"
+      w.puts "  puts line.chomp + '.new'"
+      w.puts "end"
+      w.close
+      assert_match("Can't do inplace edit for stdio; skipping", e.read)
+      assert_equal("", r.read)
+    end
+  end
+
+  def test_inplace_stdin2
+    t = make_tempfile
+
+    EnvUtil.rubyexec("-") do |w, r, e|
+      w.puts "ARGF.inplace_mode = '.bak'"
+      w.puts "while line = ARGF.gets"
+      w.puts "  puts line.chomp + '.new'"
+      w.puts "end"
+      w.close
+      assert_match("Can't do inplace edit for stdio", e.read)
+      assert_equal("", r.read)
+    end
+  end
+
+  def test_encoding
+    ruby('-e', <<-SRC, @t1.path, @t2.path, @t3.path) do |f|
+      p ARGF.external_encoding.is_a?(Encoding)
+      p ARGF.internal_encoding.is_a?(Encoding)
+      ARGF.gets
+      p ARGF.external_encoding.is_a?(Encoding)
+      p ARGF.internal_encoding
+    SRC
+      assert_equal("true\ntrue\ntrue\nnil\n", f.read)
+    end
+  end
+
+  def test_tell
+    ruby('-e', <<-SRC, @t1.path, @t2.path, @t3.path) do |f|
+      begin
+        loop do
+          p ARGF.tell
+          p ARGF.gets
+        end
+      rescue ArgumentError
+        puts "end"
+      end
+    SRC
+      a = f.read.split("\n")
+      [0, 2, 4, 2, 4, 2, 4].map {|i| i.to_s }.
+      zip((1..6).map {|i| '"' + i.to_s + '\n"' } + ["nil"]).flatten.
+      each do |x|
+        assert_equal(x, a.shift)
+      end
+      assert_equal('end', a.shift)
+    end
+  end
+
+  def test_seek
+    ruby('-e', <<-SRC, @t1.path, @t2.path, @t3.path) do |f|
+      ARGF.seek(4)
+      p ARGF.gets #=> "3"
+      ARGF.seek(0, IO::SEEK_END)
+      p ARGF.gets #=> "5"
+      ARGF.seek(4)
+      p ARGF.gets #=> nil
+      begin
+        ARGF.seek(0)
+      rescue
+        puts "end"
+      end
+    SRC
+      a = f.read.split("\n")
+      assert_equal('"3\n"', a.shift)
+      assert_equal('"5\n"', a.shift)
+      assert_equal('nil', a.shift)
+      assert_equal('end', a.shift)
+    end
+  end
+
+  def test_set_pos
+    ruby('-e', <<-SRC, @t1.path, @t2.path, @t3.path) do |f|
+      ARGF.pos = 4
+      p ARGF.gets #=> "3"
+      ARGF.pos = 4
+      p ARGF.gets #=> "5"
+      ARGF.pos = 4
+      p ARGF.gets #=> nil
+      begin
+        ARGF.pos = 4
+      rescue
+        puts "end"
+      end
+    SRC
+      a = f.read.split("\n")
+      assert_equal('"3\n"', a.shift)
+      assert_equal('"5\n"', a.shift)
+      assert_equal('nil', a.shift)
+      assert_equal('end', a.shift)
+    end
+  end
+
+  def test_rewind
+    ruby('-e', <<-SRC, @t1.path, @t2.path, @t3.path) do |f|
+      ARGF.pos = 4
+      ARGF.rewind
+      p ARGF.gets #=> "1"
+      ARGF.pos = 4
+      p ARGF.gets #=> "3"
+      ARGF.pos = 4
+      p ARGF.gets #=> "5"
+      ARGF.pos = 4
+      p ARGF.gets #=> nil
+      begin
+        ARGF.rewind
+      rescue
+        puts "end"
+      end
+    SRC
+      a = f.read.split("\n")
+      assert_equal('"1\n"', a.shift)
+      assert_equal('"3\n"', a.shift)
+      assert_equal('"5\n"', a.shift)
+      assert_equal('nil', a.shift)
+      assert_equal('end', a.shift)
+    end
+  end
+
+  def test_fileno
+    ruby('-e', <<-SRC, @t1.path, @t2.path, @t3.path) do |f|
+      p ARGF.fileno
+      ARGF.gets
+      ARGF.gets
+      p ARGF.fileno
+      ARGF.gets
+      ARGF.gets
+      p ARGF.fileno
+      ARGF.gets
+      ARGF.gets
+      p ARGF.fileno
+      ARGF.gets
+      begin
+        ARGF.fileno
+      rescue
+        puts "end"
+      end
+    SRC
+      a = f.read.split("\n")
+      fd1, fd2, fd3, fd4, tag = a
+      assert_match(/^\d+$/, fd1)
+      assert_match(/^\d+$/, fd2)
+      assert_match(/^\d+$/, fd3)
+      assert_match(/^\d+$/, fd4)
+      assert_equal('end', tag)
+    end
+  end
+
+  def test_to_io
+    ruby('-e', <<-SRC, @t1.path, @t2.path, @t3.path) do |f|
+      8.times do
+        p ARGF.to_io
+        ARGF.gets
+      end
+    SRC
+      a = f.read.split("\n")
+      f11, f12, f13, f21, f22, f31, f32, f4 = a
+      assert_equal(f11, f12)
+      assert_equal(f11, f13)
+      assert_equal(f21, f22)
+      assert_equal(f31, f32)
+      assert_match(/\(closed\)/, f4)
+      f4.sub!(/ \(closed\)/, "")
+      assert_equal(f31, f4)
+    end
+  end
+
+  def test_eof
+    ruby('-e', <<-SRC, @t1.path, @t2.path, @t3.path) do |f|
+      begin
+        8.times do
+          p ARGF.eof?
+          ARGF.gets
+        end
+      rescue IOError
+        puts "end"
+      end
+    SRC
+      a = f.read.split("\n")
+      ((%w(true false) * 4).take(7) + %w(end)).each do |x|
+        assert_equal(x, a.shift)
+      end
+    end
+  end
+
+  def test_read
+    ruby('-e', "p ARGF.read(8)", @t1.path, @t2.path, @t3.path) do |f|
+      assert_equal("\"1\\n2\\n3\\n4\\n\"\n", f.read)
+    end
+  end
+
+  def test_read2
+    ruby('-e', <<-SRC, @t1.path, @t2.path, @t3.path) do |f|
+      s = ""
+      ARGF.read(8, s)
+      p s
+    SRC
+      assert_equal("\"1\\n2\\n3\\n4\\n\"\n", f.read)
+    end
+  end
+
+  def test_read3
+    ruby('-e', <<-SRC, @t1.path, @t2.path, @t3.path) do |f|
+      nil while ARGF.gets
+      p ARGF.read
+      p ARGF.read(0, "")
+    SRC
+      assert_equal("nil\n\"\"\n", f.read)
+    end
+  end
+
+  def test_readpartial
+    ruby('-e', <<-SRC, @t1.path, @t2.path, @t3.path) do |f|
+      s = ""
+      begin
+        loop do
+          s << ARGF.readpartial(1)
+          t = ""; ARGF.readpartial(1, t); s << t
+        end
+      rescue EOFError
+        puts s
+      end
+    SRC
+      assert_equal("1\n2\n3\n4\n5\n6\n", f.read)
+    end
+  end
+
+  def test_readpartial2
+    ruby('-e', <<-SRC) do |f|
+      s = ""
+      begin
+        loop do
+          s << ARGF.readpartial(1)
+          t = ""; ARGF.readpartial(1, t); s << t
+        end
+      rescue EOFError
+        puts s
+      end
+    SRC
+      f.puts("foo")
+      f.puts("bar")
+      f.puts("baz")
+      f.close_write
+      assert_equal("foo\nbar\nbaz\n", f.read)
+    end
+  end
+
+  def test_getc
+    ruby('-e', <<-SRC, @t1.path, @t2.path, @t3.path) do |f|
+      s = ""
+      while c = ARGF.getc
+        s << c
+      end
+      puts s
+    SRC
+      assert_equal("1\n2\n3\n4\n5\n6\n", f.read)
+    end
+  end
+
+  def test_getbyte
+    ruby('-e', <<-SRC, @t1.path, @t2.path, @t3.path) do |f|
+      s = []
+      while c = ARGF.getbyte
+        s << c
+      end
+      p s
+    SRC
+      assert_equal("[49, 10, 50, 10, 51, 10, 52, 10, 53, 10, 54, 10]\n", f.read)
+    end
+  end
+
+  def test_readchar
+    ruby('-e', <<-SRC, @t1.path, @t2.path, @t3.path) do |f|
+      s = ""
+      begin
+        while c = ARGF.readchar
+          s << c
+        end
+      rescue EOFError
+        puts s
+      end
+    SRC
+      assert_equal("1\n2\n3\n4\n5\n6\n", f.read)
+    end
+  end
+
+  def test_readbyte
+    ruby('-e', <<-SRC, @t1.path, @t2.path, @t3.path) do |f|
+      begin
+        s = []
+        while c = ARGF.readbyte
+          s << c
+        end
+      rescue EOFError
+        p s
+      end
+    SRC
+      assert_equal("[49, 10, 50, 10, 51, 10, 52, 10, 53, 10, 54, 10]\n", f.read)
+    end
+  end
+
+  def test_each_line
+    ruby('-e', <<-SRC, @t1.path, @t2.path, @t3.path) do |f|
+      s = []
+      ARGF.each_line {|l| s << l }
+      p s
+    SRC
+      assert_equal("[\"1\\n\", \"2\\n\", \"3\\n\", \"4\\n\", \"5\\n\", \"6\\n\"]\n", f.read)
+    end
+  end
+
+  def test_each_byte
+    ruby('-e', <<-SRC, @t1.path, @t2.path, @t3.path) do |f|
+      s = []
+      ARGF.each_byte {|c| s << c }
+      p s
+    SRC
+      assert_equal("[49, 10, 50, 10, 51, 10, 52, 10, 53, 10, 54, 10]\n", f.read)
+    end
+  end
+
+  def test_each_char
+    ruby('-e', <<-SRC, @t1.path, @t2.path, @t3.path) do |f|
+      s = ""
+      ARGF.each_char {|c| s << c }
+      puts s
+    SRC
+      assert_equal("1\n2\n3\n4\n5\n6\n", f.read)
+    end
+  end
+
+  def test_filename
+    ruby('-e', <<-SRC, @t1.path, @t2.path, @t3.path) do |f|
+      begin
+        puts ARGF.filename.dump
+      end while ARGF.gets
+      puts ARGF.filename.dump
+    SRC
+      a = f.read.split("\n")
+      assert_equal(@t1.path.dump, a.shift)
+      assert_equal(@t1.path.dump, a.shift)
+      assert_equal(@t1.path.dump, a.shift)
+      assert_equal(@t2.path.dump, a.shift)
+      assert_equal(@t2.path.dump, a.shift)
+      assert_equal(@t3.path.dump, a.shift)
+      assert_equal(@t3.path.dump, a.shift)
+      assert_equal(@t3.path.dump, a.shift)
+    end
+  end
+
+  def test_filename2
+    ruby('-e', <<-SRC, @t1.path, @t2.path, @t3.path) do |f|
+      begin
+        puts $FILENAME.dump
+      end while ARGF.gets
+      puts $FILENAME.dump
+    SRC
+      a = f.read.split("\n")
+      assert_equal(@t1.path.dump, a.shift)
+      assert_equal(@t1.path.dump, a.shift)
+      assert_equal(@t1.path.dump, a.shift)
+      assert_equal(@t2.path.dump, a.shift)
+      assert_equal(@t2.path.dump, a.shift)
+      assert_equal(@t3.path.dump, a.shift)
+      assert_equal(@t3.path.dump, a.shift)
+      assert_equal(@t3.path.dump, a.shift)
+    end
+  end
+
+  def test_file
+    ruby('-e', <<-SRC, @t1.path, @t2.path, @t3.path) do |f|
+      begin
+        puts ARGF.file.path.dump
+      end while ARGF.gets
+      puts ARGF.file.path.dump
+    SRC
+      a = f.read.split("\n")
+      assert_equal(@t1.path.dump, a.shift)
+      assert_equal(@t1.path.dump, a.shift)
+      assert_equal(@t1.path.dump, a.shift)
+      assert_equal(@t2.path.dump, a.shift)
+      assert_equal(@t2.path.dump, a.shift)
+      assert_equal(@t3.path.dump, a.shift)
+      assert_equal(@t3.path.dump, a.shift)
+      assert_equal(@t3.path.dump, a.shift)
+    end
+  end
+
+  def test_binmode
+    ruby('-e', "ARGF.binmode; puts ARGF.read", @t1.path, @t2.path, @t3.path) do |f|
+      assert_equal("1\n2\n3\n4\n5\n6\n", f.read)
+    end
+  end
+
+  def test_skip
+    ruby('-e', <<-SRC, @t1.path, @t2.path, @t3.path) do |f|
+      begin
+        ARGF.skip
+      rescue
+        puts "cannot skip" # ???
+      end
+      puts ARGF.gets
+      ARGF.skip
+      puts ARGF.read
+    SRC
+      assert_equal("cannot skip\n1\n3\n4\n5\n6\n", f.read)
+    end
+  end
+
+  def test_close
+    ruby('-e', <<-SRC, @t1.path, @t2.path, @t3.path) do |f|
+      ARGF.close
+      puts ARGF.read
+    SRC
+      assert_equal("3\n4\n5\n6\n", f.read)
+    end
+  end
+
+  def test_closed
+    ruby('-e', <<-SRC, @t1.path, @t2.path, @t3.path) do |f|
+      3.times do
+        p ARGF.closed?
+        ARGF.gets
+        ARGF.gets
+      end
+      p ARGF.closed?
+      ARGF.gets
+      p ARGF.closed?
+    SRC
+      assert_equal("false\nfalse\nfalse\nfalse\ntrue\n", f.read)
+    end
+  end
+
+  def test_argv
+    ruby('-e', "p ARGF.argv; p $*", @t1.path, @t2.path, @t3.path) do |f|
+      assert_equal([@t1.path, @t2.path, @t3.path].inspect, f.gets.chomp)
+      assert_equal([@t1.path, @t2.path, @t3.path].inspect, f.gets.chomp)
+    end
+  end
+end

Modified: MacRuby/branches/testing/test/ruby/test_array.rb
===================================================================
--- MacRuby/branches/testing/test/ruby/test_array.rb	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/test/ruby/test_array.rb	2008-06-05 08:33:02 UTC (rev 249)
@@ -74,7 +74,7 @@
   end
 
   def test_split_0
-    x = "The Boassert of Mormon"
+    x = "The Book of Mormon"
     assert_equal(x.reverse, x.split(//).reverse!.join)
     assert_equal(x.reverse, x.reverse!)
     assert_equal("g:n:i:r:t:s: :e:t:y:b: :1", "1 byte string".split(//).reverse.join(":"))
@@ -539,6 +539,7 @@
 
   def test_count
     a = @cls[1, 2, 3, 1, 2]
+    assert_equal(5, a._count)
     assert_equal(2, a._count(1))
     assert_equal(3, a._count {|x| x % 2 == 1 })
     assert_equal(2, a._count(1) {|x| x % 2 == 1 })
@@ -726,6 +727,20 @@
                  @cls[@cls[@cls[@cls[], at cls[]], at cls[@cls[]], at cls[]], at cls[@cls[@cls[]]]].flatten)
   end
 
+  def test_flatten_with_callcc
+    respond_to?(:callcc, true) or require 'continuation'
+    o = Object.new
+    def o.to_ary() callcc {|k| @cont = k; [1,2,3]} end
+    begin
+      assert_equal([10, 20, 1, 2, 3, 30, 1, 2, 3, 40], [10, 20, o, 30, o, 40].flatten)
+    rescue => e
+    else
+      o.instance_eval {@cont}.call
+    end
+    assert_instance_of(RuntimeError, e, '[ruby-dev:34798]')
+    assert_match(/reentered/, e.message, '[ruby-dev:34798]')
+  end
+
   def test_hash
     a1 = @cls[ 'cat', 'dog' ]
     a2 = @cls[ 'cat', 'dog' ]
@@ -813,14 +828,6 @@
     assert_equal(@cls[], a)
   end
 
-  def test_nitems
-    assert_equal(0, @cls[].nitems)
-    assert_equal(1, @cls[1].nitems)
-    assert_equal(1, @cls[1, nil].nitems)
-    assert_equal(1, @cls[nil, 1].nitems)
-    assert_equal(3, @cls[1, nil, nil, 2, nil, 3, nil].nitems)
-  end
-
   def test_pack
     a = @cls[*%w( cat wombat x yy)]
     assert_equal("catwomx  yy ", a.pack("A3A3A3A3"))
@@ -1155,6 +1162,16 @@
     assert_match(/reentered/, e.message, '[ruby-core:16679]')
   end
 
+  def test_sort_with_replace
+    xary = (1..100).to_a
+    100.times do
+      ary = (1..100).to_a
+      ary.sort! {|a,b| ary.replace(xary); a <=> b}
+      GC.start
+      assert_equal(xary, ary, '[ruby-dev:34732]')
+    end
+  end
+
   def test_to_a
     a = @cls[ 1, 2, 3 ]
     a_id = a.__id__
@@ -1294,14 +1311,24 @@
     assert_raise(SecurityError) do
       Thread.new do
         $SAFE = 4
-        a.shift
+       a.shift
       end.value
     end
   end
 
+  LONGP = [127, 63, 31, 15, 7].map {|x| 2**x-1 }.find do |x|
+    begin
+      [].first(x)
+    rescue ArgumentError
+      true
+    rescue RangeError
+      false
+    end
+  end
+
   def test_ary_new
     assert_raise(ArgumentError) { [].to_enum.first(-1) }
-    assert_raise(ArgumentError) { [].to_enum.first(2**31-1) }
+    assert_raise(ArgumentError) { [].to_enum.first(LONGP) }
   end
 
   def test_try_convert
@@ -1314,7 +1341,7 @@
     assert_nothing_raised { Array.new { } }
     assert_equal([1, 2, 3], Array.new([1, 2, 3]))
     assert_raise(ArgumentError) { Array.new(-1, 1) }
-    assert_raise(ArgumentError) { Array.new(2**31-1, 1) }
+    assert_raise(ArgumentError) { Array.new(LONGP, 1) }
     assert_equal([1, 1, 1], Array.new(3, 1))
     assert_equal([1, 1, 1], Array.new(3) { 1 })
     assert_equal([1, 1, 1], Array.new(3, 1) { 1 })
@@ -1322,8 +1349,8 @@
 
   def test_aset
     assert_raise(IndexError) { [0][-2] = 1 }
-    assert_raise(ArgumentError) { [0][2**31-1] = 2 }
-    assert_raise(ArgumentError) { [0][2**30-1] = 3 }
+    assert_raise(ArgumentError) { [0][LONGP] = 2 }
+    assert_raise(ArgumentError) { [0][(LONGP + 1) / 2 - 1] = 2 }
     a = [0]
     a[2] = 4
     assert_equal([0, nil, 4], a)
@@ -1461,11 +1488,11 @@
   end
 
   def test_fill2
-    assert_raise(ArgumentError) { [].fill(0, 1, 2**31-1) }
+    assert_raise(ArgumentError) { [].fill(0, 1, LONGP) }
   end
 
   def test_times
-    assert_raise(ArgumentError) { [0, 0, 0, 0] * (2**29) }
+    assert_raise(ArgumentError) { [0, 0, 0, 0] * ((LONGP + 1) / 4) }
   end
 
   def test_equal
@@ -1484,10 +1511,6 @@
     assert_equal(a.hash, b.hash)
   end
 
-  def test_nitems2
-    assert_equal(3, [5,6,7,8,9].nitems { |x| x % 2 != 0 })
-  end
-
   def test_flatten2
     a = []
     a << a
@@ -1533,17 +1556,6 @@
     assert_equal([5, 3, 1], r)
   end
 
-  def test_each2
-    a = [0, 1, 2, 3, 4, 5]
-    r = []
-    a.each do |x|
-      r << x
-      a.pop
-      a.pop
-    end
-    assert_equal([0, 1], r)
-  end
-
   def test_combination2
     assert_raise(RangeError) do
       (0..100).to_a.combination(50) {}

Copied: MacRuby/branches/testing/test/ruby/test_big5.rb (from rev 248, MacRuby/trunk/test/ruby/test_big5.rb)
===================================================================
--- MacRuby/branches/testing/test/ruby/test_big5.rb	                        (rev 0)
+++ MacRuby/branches/testing/test/ruby/test_big5.rb	2008-06-05 08:33:02 UTC (rev 249)
@@ -0,0 +1,28 @@
+require "test/unit"
+
+class TestBig5 < Test::Unit::TestCase
+  def s(s)
+    s.force_encoding("big5")
+  end
+
+  def test_mbc_enc_len
+    assert_equal(1, s("\xa1\xa1").size)
+  end
+
+  def test_mbc_to_code
+    assert_equal(0xa1a1, s("\xa1\xa1").ord)
+  end
+
+  def test_code_to_mbc
+    assert_equal(s("\xa1\xa1"), 0xa1a1.chr("big5"))
+  end
+
+  def test_mbc_case_fold
+    r = Regexp.new(s("(\xa1\xa1)\\1"), "i")
+    assert_match(r, s("\xa1\xa1\xa1\xa1"))
+  end
+
+  def test_left_adjust_char_head
+    assert_equal(s("\xa1\xa1"), s("\xa1\xa1\xa1\xa1").chop)
+  end
+end

Modified: MacRuby/branches/testing/test/ruby/test_class.rb
===================================================================
--- MacRuby/branches/testing/test/ruby/test_class.rb	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/test/ruby/test_class.rb	2008-06-05 08:33:02 UTC (rev 249)
@@ -1,6 +1,10 @@
 require 'test/unit'
+require_relative 'envutil'
 
 class TestClass < Test::Unit::TestCase
+  def ruby(*r, &b)
+    EnvUtil.rubyexec(*r, &b)
+  end
 
   # ------------------
   # Various test classes
@@ -105,4 +109,46 @@
     end
   end
 
+  def test_check_inheritable
+    assert_raise(TypeError) { Class.new(Object.new) }
+
+    o = Object.new
+    c = class << o; self; end
+    assert_raise(TypeError) { Class.new(c) }
+
+    assert_nothing_raised { Class.new(Class) } # is it OK?
+    assert_raise(TypeError) { eval("class Foo < Class; end") }
+  end
+
+  def test_initialize_copy
+    c = Class.new
+    assert_raise(TypeError) { c.instance_eval { initialize_copy(1) } }
+
+    o = Object.new
+    c = class << o; self; end
+    assert_raise(TypeError) { c.dup }
+  end
+
+  def test_singleton_class
+    assert_raise(TypeError) { 1.extend(Module.new) }
+    assert_raise(TypeError) { :foo.extend(Module.new) }
+
+    ruby do |w, r, e|
+      w.puts "module Foo; def foo; :foo; end; end"
+      w.puts "false.extend(Foo)"
+      w.puts "true.extend(Foo)"
+      w.puts "p false.foo"
+      w.puts "p true.foo"
+      w.puts "p FalseClass.include?(Foo)"
+      w.puts "p TrueClass.include?(Foo)"
+      w.close
+      assert_equal("", e.read)
+      assert_equal(":foo\n:foo\ntrue\ntrue", r.read.chomp)
+    end
+  end
+
+  def test_uninitialized
+    assert_raise(TypeError) { Class.allocate.new }
+    assert_raise(TypeError) { Class.allocate.superclass }
+  end
 end

Modified: MacRuby/branches/testing/test/ruby/test_continuation.rb
===================================================================
--- MacRuby/branches/testing/test/ruby/test_continuation.rb	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/test/ruby/test_continuation.rb	2008-06-05 08:33:02 UTC (rev 249)
@@ -51,5 +51,31 @@
       c.call
     }
   end
+
+  def test_ary_flatten
+    assert_normal_exit %q{
+      require 'continuation'
+      n = 0
+      o = Object.new
+      def o.to_ary() callcc {|k| $k = k; [1,2,3]} end
+      [10,20,o,30,o,40].flatten.inspect
+      n += 1
+      $k.call if n < 100
+    }, '[ruby-dev:34798]'
+  end
+
+  def test_marshal_dump
+    assert_normal_exit %q{
+      require 'continuation'
+      n = 0
+      o = Object.new
+      def o.marshal_dump() callcc {|k| $k = k };  "fofof" end
+      a = [1,2,3,o,4,5,6]
+      Marshal.dump(a).inspect
+      n += 1
+      $k.call if n < 100
+    }, '[ruby-dev:34802]'
+  end
+
 end
 

Copied: MacRuby/branches/testing/test/ruby/test_cp949.rb (from rev 248, MacRuby/trunk/test/ruby/test_cp949.rb)
===================================================================
--- MacRuby/branches/testing/test/ruby/test_cp949.rb	                        (rev 0)
+++ MacRuby/branches/testing/test/ruby/test_cp949.rb	2008-06-05 08:33:02 UTC (rev 249)
@@ -0,0 +1,28 @@
+require "test/unit"
+
+class TestCP949 < Test::Unit::TestCase
+  def s(s)
+    s.force_encoding("cp949")
+  end
+
+  def test_mbc_enc_len
+    assert_equal(1, s("\xa1\xa1").size)
+  end
+
+  def test_mbc_to_code
+    assert_equal(0xa1a1, s("\xa1\xa1").ord)
+  end
+
+  def test_code_to_mbc
+    assert_equal(s("\xa1\xa1"), 0xa1a1.chr("cp949"))
+  end
+
+  def test_mbc_case_fold
+    r = Regexp.new(s("(\xa1\xa1)\\1"), "i")
+    assert_match(r, s("\xa1\xa1\xa1\xa1"))
+  end
+
+  def test_left_adjust_char_head
+    assert_equal(s("\xa1\xa1"), s("\xa1\xa1\xa1\xa1").chop)
+  end
+end

Modified: MacRuby/branches/testing/test/ruby/test_enum.rb
===================================================================
--- MacRuby/branches/testing/test/ruby/test_enum.rb	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/test/ruby/test_enum.rb	2008-06-05 08:33:02 UTC (rev 249)
@@ -30,6 +30,7 @@
   end
 
   def test_count
+    assert_equal(5, @obj.count)
     assert_equal(2, @obj.count(1))
     assert_equal(3, @obj.count {|x| x % 2 == 1 })
     assert_equal(2, @obj.count(1) {|x| x % 2 == 1 })

Copied: MacRuby/branches/testing/test/ruby/test_euc_jp.rb (from rev 248, MacRuby/trunk/test/ruby/test_euc_jp.rb)
===================================================================
--- MacRuby/branches/testing/test/ruby/test_euc_jp.rb	                        (rev 0)
+++ MacRuby/branches/testing/test/ruby/test_euc_jp.rb	2008-06-05 08:33:02 UTC (rev 249)
@@ -0,0 +1,20 @@
+# vim: set fileencoding=euc-jp
+
+require "test/unit"
+
+class TestEUC_JP < Test::Unit::TestCase
+  def test_mbc_case_fold
+    assert_match(/(\xA3\xE1)(a)\1\2/i, "\xA3\xE1a\xA3\xE1A")
+    assert_no_match(/(\xA3\xE1)(a)\1\2/i, "\xA3\xE1a\xA3\xC1A")
+  end
+
+  def test_property
+    assert_match(/\xA4\xA2{0}\p{Hiragana}{4}/, "\xA4Ҥ餬\xA4\xCA")
+    assert_no_match(/\xA4\xA2{0}\p{Hiragana}{4}/, "\xA5\xAB\xA5\xBF\xA5\xAB\xA5\xCA")
+    assert_no_match(/\xA4\xA2{0}\p{Hiragana}{4}/, "\xB4\xC1\xBB\xFA\xB4\xC1\xBB\xFA")
+    assert_no_match(/\xA4\xA2{0}\p{Katakana}{4}/, "\xA4Ҥ餬\xA4\xCA")
+    assert_match(/\xA4\xA2{0}\p{Katakana}{4}/, "\xA5\xAB\xA5\xBF\xA5\xAB\xA5\xCA")
+    assert_no_match(/\xA4\xA2{0}\p{Katakana}{4}/, "\xB4\xC1\xBB\xFA\xB4\xC1\xBB\xFA")
+    assert_raise(RegexpError) { Regexp.new('\xA4\xA2{0}\p{foobarbaz}') }
+  end
+end

Copied: MacRuby/branches/testing/test/ruby/test_euc_kr.rb (from rev 248, MacRuby/trunk/test/ruby/test_euc_kr.rb)
===================================================================
--- MacRuby/branches/testing/test/ruby/test_euc_kr.rb	                        (rev 0)
+++ MacRuby/branches/testing/test/ruby/test_euc_kr.rb	2008-06-05 08:33:02 UTC (rev 249)
@@ -0,0 +1,28 @@
+require "test/unit"
+
+class TestEucKr < Test::Unit::TestCase
+  def s(s)
+    s.force_encoding("euc-kr")
+  end
+
+  def test_mbc_enc_len
+    assert_equal(1, s("\xa1\xa1").size)
+  end
+
+  def test_mbc_to_code
+    assert_equal(0xa1a1, s("\xa1\xa1").ord)
+  end
+
+  def test_code_to_mbc
+    assert_equal(s("\xa1\xa1"), 0xa1a1.chr("euc-kr"))
+  end
+
+  def test_mbc_case_fold
+    r = Regexp.new(s("(\xa1\xa1)\\1"), "i")
+    assert_match(r, s("\xa1\xa1\xa1\xa1"))
+  end
+
+  def test_left_adjust_char_head
+    assert_equal(s("\xa1\xa1"), s("\xa1\xa1\xa1\xa1").chop)
+  end
+end

Copied: MacRuby/branches/testing/test/ruby/test_euc_tw.rb (from rev 248, MacRuby/trunk/test/ruby/test_euc_tw.rb)
===================================================================
--- MacRuby/branches/testing/test/ruby/test_euc_tw.rb	                        (rev 0)
+++ MacRuby/branches/testing/test/ruby/test_euc_tw.rb	2008-06-05 08:33:02 UTC (rev 249)
@@ -0,0 +1,28 @@
+require "test/unit"
+
+class TestEucTw < Test::Unit::TestCase
+  def s(s)
+    s.force_encoding("euc-tw")
+  end
+
+  def test_mbc_enc_len
+    assert_equal(1, s("\xa1\xa1").size)
+  end
+
+  def test_mbc_to_code
+    assert_equal(0xa1a1, s("\xa1\xa1").ord)
+  end
+
+  def test_code_to_mbc
+    assert_equal(s("\xa1\xa1"), 0xa1a1.chr("euc-tw"))
+  end
+
+  def test_mbc_case_fold
+    r = Regexp.new(s("(\xa1\xa1)\\1"), "i")
+    assert_match(r, s("\xa1\xa1\xa1\xa1"))
+  end
+
+  def test_left_adjust_char_head
+    assert_equal(s("\xa1\xa1"), s("\xa1\xa1\xa1\xa1").chop)
+  end
+end

Modified: MacRuby/branches/testing/test/ruby/test_eval.rb
===================================================================
--- MacRuby/branches/testing/test/ruby/test_eval.rb	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/test/ruby/test_eval.rb	2008-06-05 08:33:02 UTC (rev 249)
@@ -139,7 +139,7 @@
 
     assert_equal 11,    o.instance_eval("11")
     assert_equal 12,    o.instance_eval("@ivar")
-    assert_raise(NameError) {o.instance_eval("@@cvar")}
+    assert_equal 13,    o.instance_eval("@@cvar")
     assert_equal 14,    o.instance_eval("$gvar__eval")
     assert_equal 15,    o.instance_eval("Const")
     assert_equal 16,    o.instance_eval("7 + 9")
@@ -149,7 +149,7 @@
 
     1.times {
       assert_equal 12,  o.instance_eval("@ivar")
-      assert_raise(NameError) {o.instance_eval("@@cvar")}
+      assert_equal 13,  o.instance_eval("@@cvar")
       assert_equal 14,  o.instance_eval("$gvar__eval")
       assert_equal 15,  o.instance_eval("Const")
     }
@@ -169,7 +169,7 @@
 
     assert_equal 11,    o.instance_eval { 11 }
     assert_equal 12,    o.instance_eval { @ivar }
-    assert_raise(NameError) {o.instance_eval{ @@cvar }}
+    assert_equal 13,    o.instance_eval { @@cvar }
     assert_equal 14,    o.instance_eval { $gvar__eval }
     assert_equal 15,    o.instance_eval { Const }
     assert_equal 16,    o.instance_eval { 7 + 9 }
@@ -179,7 +179,7 @@
 
     1.times {
       assert_equal 12,  o.instance_eval { @ivar }
-      assert_raise(NameError) {o.instance_eval{ @@cvar }}
+      assert_equal 13,  o.instance_eval { @@cvar }
       assert_equal 14,  o.instance_eval { $gvar__eval }
       assert_equal 15,  o.instance_eval { Const }
     }
@@ -187,8 +187,10 @@
 
   def test_instance_eval_cvar
     [Object.new, [], 7, :sym, true, false, nil].each do |obj|
-      assert_raise(NameError){obj.instance_eval("@@cvar")}
-      assert_raise(NameError){obj.instance_eval{@@cvar}}
+      assert_equal(13, obj.instance_eval("@@cvar"))
+      assert_equal(13, obj.instance_eval{@@cvar})
+      # assert_raise(NameError){obj.instance_eval("@@cvar")}
+      # assert_raise(NameError){obj.instance_eval{@@cvar}}
     end
   end
 
@@ -339,9 +341,10 @@
   end
 
   def test_cvar_scope_with_instance_eval
+    # TODO: check
     Fixnum.class_eval "@@test_cvar_scope_with_instance_eval = 1" # depends on [ruby-dev:24229]
     @@test_cvar_scope_with_instance_eval = 4
-    assert_equal(1, 1.instance_eval("@@test_cvar_scope_with_instance_eval"), "[ruby-dev:24223]")
+    assert_equal(4, 1.instance_eval("@@test_cvar_scope_with_instance_eval"), "[ruby-dev:24223]")
     Fixnum.__send__(:remove_class_variable, :@@test_cvar_scope_with_instance_eval)
   end
 
@@ -358,6 +361,19 @@
     }
   end
 
+  def test_define_method_block
+    cc = Class.new do
+      define_method(:foo) {|&block|
+        block.call if block
+      }
+    end
+
+    c = cc.new
+    x = "ng"
+    c.foo() {x = "ok"}
+    assert_equal("ok", x)
+  end
+
   def test_eval_using_integer_as_binding
     assert_raise(TypeError) { eval("", 1) }
   end

Modified: MacRuby/branches/testing/test/ruby/test_file.rb
===================================================================
--- MacRuby/branches/testing/test/ruby/test_file.rb	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/test/ruby/test_file.rb	2008-06-05 08:33:02 UTC (rev 249)
@@ -115,4 +115,7 @@
     }
   end
 
+  def test_uninitialized
+    assert_raise(TypeError) { File::Stat.allocate.readable? }
+  end
 end

Modified: MacRuby/branches/testing/test/ruby/test_file_exhaustive.rb
===================================================================
--- MacRuby/branches/testing/test/ruby/test_file_exhaustive.rb	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/test/ruby/test_file_exhaustive.rb	2008-06-05 08:33:02 UTC (rev 249)
@@ -20,7 +20,7 @@
     end
     begin
       File.link(@file, @hardlinkfile)
-    rescue NotImplementedError
+    rescue NotImplementedError, Errno::EINVAL	# EINVAL for Windows Vista
       @hardlinkfile = nil
     end
   end
@@ -411,6 +411,17 @@
   def test_extname
     assert(".test", File.extname(@file))
     assert_equal("", File.extname("foo"))
+    assert_equal("", File.extname("/foo"))
+    assert_equal("", File.extname(".foo"))
+    assert_equal("", File.extname("/.foo"))
+    assert_equal("", File.extname("bar/.foo"))
+    assert_equal("", File.extname("/bar/.foo"))
+    assert_equal(".ext", File.extname("foo.ext"))
+    assert_equal(".ext", File.extname("/foo.ext"))
+    assert_equal(".ext", File.extname(".foo.ext"))
+    assert_equal(".ext", File.extname("/.foo.ext"))
+    assert_equal(".ext", File.extname("bar/.foo.ext"))
+    assert_equal(".ext", File.extname("/bar/.foo.ext"))
     assert_equal("", File.extname(""))
     if /cygwin|mingw|mswin|bccwin/ =~ RUBY_PLATFORM
       assert_equal("", File.extname("foo "))

Copied: MacRuby/branches/testing/test/ruby/test_gb18030.rb (from rev 248, MacRuby/trunk/test/ruby/test_gb18030.rb)
===================================================================
--- MacRuby/branches/testing/test/ruby/test_gb18030.rb	                        (rev 0)
+++ MacRuby/branches/testing/test/ruby/test_gb18030.rb	2008-06-05 08:33:02 UTC (rev 249)
@@ -0,0 +1,125 @@
+require "test/unit"
+
+class TestGB18030 < Test::Unit::TestCase
+  def s(s)
+    s.force_encoding("gb18030")
+  end
+
+  def test_mbc_enc_len
+    assert_equal(1, s("\x81\x40").size)
+    assert_equal(1, s("\x81\x30\x81\x30").size)
+  end
+
+  def test_mbc_to_code
+    assert_equal(0x8140, s("\x81\x40").ord)
+  end
+
+  def test_code_to_mbc
+    assert_equal(s("\x81\x40"), 0x8140.chr("gb18030"))
+  end
+
+  def test_mbc_case_fold
+    r = Regexp.new(s("(\x81\x40)\\1"), "i")
+    assert_match(r, s("\x81\x40\x81\x40"))
+  end
+
+  def scheck(c, i)
+    assert_equal(s(c.reverse.take(c.size - i).join), s(c.reverse.join).chop)
+  end
+
+  def fcheck(c)
+    assert_raise(ArgumentError) { s(c.reverse.join).chop }
+  end
+
+  def test_left_adjust_char_head
+    # C1: 00-2f, 3a-3f, 7f, ff
+    # C2: 40-7e, 80
+    # C4: 30-39
+    # CM: 81-fe
+    c1 = "\x2f"
+    c2 = "\x40"
+    c4 = "\x30"
+    cm = "\x81"
+
+    # S_START-c1
+    # S_START-c2-S_one_C2-0
+    # S_START-c2-S_one_C2-c1
+    # S_START-c2-S_one_C2-cm-S_odd_CM_one_CX-c1
+    # S_START-c2-S_one_C2-cm-S_odd_CM_one_CX-cm-S_even_CM_one_CX-c1
+    # S_START-c2-S_one_C2-cm-S_odd_CM_one_CX-cm-S_even_CM_one_CX-cm-S_odd_CM_one_CX(rec)
+    # S_START-c4-S_one_C4-c1
+    # S_START-c4-S_one_C4-cm-S_one_CMC4-c1
+    # S_START-c4-S_one_C4-cm-S_one_CMC4-c4-S_one_C4_odd_CMC4-c1
+    # S_START-c4-S_one_C4-cm-S_one_CMC4-c4-S_one_C4_odd_CMC4-cm-S_even_CMC4-c1
+    # S_START-c4-S_one_C4-cm-S_one_CMC4-c4-S_one_C4_odd_CMC4-cm-S_even_CMC4-c4-S_one_C4_even_CMC4-c1
+    # S_START-c4-S_one_C4-cm-S_one_CMC4-c4-S_one_C4_odd_CMC4-cm-S_even_CMC4-c4-S_one_C4_even_CMC4-cm-S_odd_CMC4-c1
+    # S_START-c4-S_one_C4-cm-S_one_CMC4-c4-S_one_C4_odd_CMC4-cm-S_even_CMC4-c4-S_one_C4_even_CMC4-cm-S_odd_CMC4-c4-S_one_C4_odd_CMC4(rec)
+    # S_START-c4-S_one_C4-cm-S_one_CMC4-c4-S_one_C4_odd_CMC4-cm-S_even_CMC4-c4-S_one_C4_even_CMC4-cm-S_odd_CMC4-cm-S_odd_CM_odd_CMC4-c1
+    # S_START-c4-S_one_C4-cm-S_one_CMC4-c4-S_one_C4_odd_CMC4-cm-S_even_CMC4-c4-S_one_C4_even_CMC4-cm-S_odd_CMC4-cm-S_odd_CM_odd_CMC4-cm-S_even_CM_odd_CMC4-c1
+    # S_START-c4-S_one_C4-cm-S_one_CMC4-c4-S_one_C4_odd_CMC4-cm-S_even_CMC4-c4-S_one_C4_even_CMC4-cm-S_odd_CMC4-cm-S_odd_CM_odd_CMC4-cm-S_even_CM_odd_CMC4-cm-S_odd_CM_odd_CMC4(rec)
+    # S_START-c4-S_one_C4-cm-S_one_CMC4-c4-S_one_C4_odd_CMC4-cm-S_even_CMC4-cm-S_odd_CM_even_CMC4-c1
+    # S_START-c4-S_one_C4-cm-S_one_CMC4-c4-S_one_C4_odd_CMC4-cm-S_even_CMC4-cm-S_odd_CM_even_CMC4-cm-S_even_CM_even_CMC4-c1
+    # S_START-c4-S_one_C4-cm-S_one_CMC4-c4-S_one_C4_odd_CMC4-cm-S_even_CMC4-cm-S_odd_CM_even_CMC4-cm-S_even_CM_even_CMC4-cm-S_odd_CM_even_CMC4(rec)
+    # S_START-c4-S_one_C4-cm-S_one_CMC4-cm-S_even_CM_one_CX(rec)
+    # S_START-cm-S_one_CM-c1
+    # S_START-cm-S_one_CM-c4-S_odd_C4CM-c1
+    # S_START-cm-S_one_CM-c4-S_odd_C4CM-cm-S_one_CM_odd_C4CM-c1
+    # S_START-cm-S_one_CM-c4-S_odd_C4CM-cm-S_one_CM_odd_C4CM-c4-S_even_C4CM-c1
+    # S_START-cm-S_one_CM-c4-S_odd_C4CM-cm-S_one_CM_odd_C4CM-c4-S_even_C4CM-cm-S_one_CM_even_C4CM-c1
+    # S_START-cm-S_one_CM-c4-S_odd_C4CM-cm-S_one_CM_odd_C4CM-c4-S_even_C4CM-cm-S_one_CM_even_C4CM-c4-S_odd_C4CM(rec)
+    # S_START-cm-S_one_CM-c4-S_odd_C4CM-cm-S_one_CM_odd_C4CM-c4-S_even_C4CM-cm-S_one_CM_even_C4CM-cm-S_even_CM_even_C4CM-c1
+    # S_START-cm-S_one_CM-c4-S_odd_C4CM-cm-S_one_CM_odd_C4CM-c4-S_even_C4CM-cm-S_one_CM_even_C4CM-cm-S_even_CM_even_C4CM-cm-S_odd_CM_even_C4CM-c1
+    # S_START-cm-S_one_CM-c4-S_odd_C4CM-cm-S_one_CM_odd_C4CM-c4-S_even_C4CM-cm-S_one_CM_even_C4CM-cm-S_even_CM_even_C4CM-cm-S_odd_CM_even_C4CM-cm-S_even_CM_even_C4CM(rec)
+    # S_START-cm-S_one_CM-c4-S_odd_C4CM-cm-S_one_CM_odd_C4CM-cm-S_even_CM_odd_C4CM-c1
+    # S_START-cm-S_one_CM-c4-S_odd_C4CM-cm-S_one_CM_odd_C4CM-cm-S_even_CM_odd_C4CM-cm-S_odd_CM_odd_C4CM-c1
+    # S_START-cm-S_one_CM-c4-S_odd_C4CM-cm-S_one_CM_odd_C4CM-cm-S_even_CM_odd_C4CM-cm-S_odd_CM_odd_C4CM-cm-S_even_CM_odd_C4CM(rec)
+    # S_START-cm-S_one_CM-cm-S_odd_CM_one_CX(rec)
+
+    scheck([c1], 1)
+    scheck([c2], 1)
+    scheck([c2, c1], 1)
+    scheck([c2, cm, c1], 2)
+    scheck([c2, cm, cm, c1], 1)
+    scheck([c2, cm, cm, cm], 2)
+    scheck([c4], 1)
+    scheck([c4, c1], 1)
+    scheck([c4, cm], 2)
+    fcheck([c4, cm, c1])
+    fcheck([c4, cm, c4, c1])
+    scheck([c4, cm, c4, cm], 4)
+    scheck([c4, cm, c4, cm, c1], 4)
+    scheck([c4, cm, c4, cm, c4], 4)
+    scheck([c4, cm, c4, cm, c4, c1], 4)
+    fcheck([c4, cm, c4, cm, c4, cm])
+    fcheck([c4, cm, c4, cm, c4, cm, c1])
+    fcheck([c4, cm, c4, cm, c4, cm, c4])
+    scheck([c4, cm, c4, cm, c4, cm, cm, c1], 4)
+    fcheck([c4, cm, c4, cm, c4, cm, cm, cm])
+    fcheck([c4, cm, c4, cm, c4, cm, cm, cm, c1])
+    scheck([c4, cm, c4, cm, c4, cm, cm, cm, cm], 4)
+    fcheck([c4, cm, c4, cm, cm, c1])
+    scheck([c4, cm, c4, cm, cm, cm], 4)
+    scheck([c4, cm, c4, cm, cm, cm, c1], 4)
+    fcheck([c4, cm, c4, cm, cm, cm, cm])
+    scheck([c4, cm, cm], 1)
+    scheck([cm], 1)
+    fcheck([cm, c1])
+    fcheck([cm, c4, c1])
+    scheck([cm, c4, cm], 3)
+    fcheck([cm, c4, cm, c1])
+    fcheck([cm, c4, cm, c4])
+    fcheck([cm, c4, cm, c4, c1])
+    fcheck([cm, c4, cm, c4, cm])
+    fcheck([cm, c4, cm, c4, cm, c1])
+    fcheck([cm, c4, cm, c4, cm, c4])
+    fcheck([cm, c4, cm, c4, cm, cm, c1])
+    fcheck([cm, c4, cm, c4, cm, cm, cm])
+    fcheck([cm, c4, cm, c4, cm, cm, cm, c1])
+    fcheck([cm, c4, cm, c4, cm, cm, cm, cm])
+    fcheck([cm, c4, cm, cm, c1])
+    fcheck([cm, c4, cm, cm, cm])
+    fcheck([cm, c4, cm, cm, cm, c1])
+    fcheck([cm, c4, cm, cm, cm, cm])
+    scheck([cm, cm], 2)
+  end
+end

Copied: MacRuby/branches/testing/test/ruby/test_gbk.rb (from rev 248, MacRuby/trunk/test/ruby/test_gbk.rb)
===================================================================
--- MacRuby/branches/testing/test/ruby/test_gbk.rb	                        (rev 0)
+++ MacRuby/branches/testing/test/ruby/test_gbk.rb	2008-06-05 08:33:02 UTC (rev 249)
@@ -0,0 +1,28 @@
+require "test/unit"
+
+class TestGBK < Test::Unit::TestCase
+  def s(s)
+    s.force_encoding("gbk")
+  end
+
+  def test_mbc_enc_len
+    assert_equal(1, s("\x81\x40").size)
+  end
+
+  def test_mbc_to_code
+    assert_equal(0x8140, s("\x81\x40").ord)
+  end
+
+  def test_code_to_mbc
+    assert_equal(s("\x81\x40"), 0x8140.chr("gbk"))
+  end
+
+  def test_mbc_case_fold
+    r = Regexp.new(s("(\x81\x40)\\1"), "i")
+    assert_match(r, s("\x81\x40\x81\x40"))
+  end
+
+  def test_left_adjust_char_head
+    assert_equal(s("\x81\x40"), s("\x81\x40\x81\x40").chop)
+  end
+end

Modified: MacRuby/branches/testing/test/ruby/test_io.rb
===================================================================
--- MacRuby/branches/testing/test/ruby/test_io.rb	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/test/ruby/test_io.rb	2008-06-05 08:33:02 UTC (rev 249)
@@ -3,6 +3,9 @@
 require 'io/nonblock'
 require 'socket'
 require 'stringio'
+require 'timeout'
+require 'tempfile'
+require_relative 'envutil'
 
 class TestIO < Test::Unit::TestCase
   def test_gets_rs
@@ -545,4 +548,679 @@
     }
   end
 
+  def safe_4
+    Thread.new do
+      Timeout.timeout(10) do
+        $SAFE = 4
+        yield
+      end
+    end.join
+  end
+
+  def pipe
+    r, w = IO.pipe
+    Timeout.timeout(10) do
+      yield(r, w)
+    end
+  ensure
+    r.close unless !r || r.closed?
+    w.close unless !w || w.closed?
+  end
+
+  def pipe2(&b)
+    a = []
+    a << IO.pipe while true
+  rescue Errno::EMFILE, Errno::ENFILE, Errno::ENOMEM
+    yield(*a.last)
+  ensure
+    a.each do |r, w|
+      r.close unless !r || r.closed?
+      w.close unless !w || w.closed?
+    end
+  end
+
+  def ruby(*args)
+    args = ['-e', '$>.write($<.read)'] if args.empty?
+    ruby = EnvUtil.rubybin
+    f = IO.popen([ruby] + args, 'r+')
+    yield(f)
+  ensure
+    f.close unless !f || f.closed?
+  end
+
+  def test_try_convert
+    assert_equal(STDOUT, IO.try_convert(STDOUT))
+    assert_equal(nil, IO.try_convert("STDOUT"))
+  end
+
+  def test_ungetc2
+    pipe do |r, w|
+      r.ungetc("0" * 10000)
+      w.write("1" * 10000)
+      w.close
+      assert_equal("0" * 10000 + "1" * 10000, r.read)
+    end
+  end
+
+  def test_write_non_writable
+    pipe do |r, w|
+      assert_raise(IOError) do
+        r.write "foobarbaz"
+      end
+    end
+  end
+
+  def test_dup
+    ruby do |f|
+      f2 = f.dup
+      f.puts "foo"
+      f2.puts "bar"
+      f.close_write
+      f2.close_write
+      assert_equal("foo\nbar\n", f.read)
+      assert_equal("", f2.read)
+    end
+
+    pipe2 do |r, w|
+      assert_raise(Errno::EMFILE, Errno::ENFILE, Errno::NOMEM) do
+        r2, w2 = r.dup, w.dup
+      end
+    end
+  end
+
+  def test_inspect
+    pipe do |r, w|
+      assert(r.inspect =~ /^#<IO:0x[0-9a-f]+>$/)
+      assert_raise(SecurityError) do
+        safe_4 { r.inspect }
+      end
+    end
+  end
+
+  def test_readpartial
+    pipe do |r, w|
+      w.write "foobarbaz"
+      w.close
+      assert_raise(ArgumentError) { r.readpartial(-1) }
+      assert_equal("fooba", r.readpartial(5))
+      r.readpartial(5, s = "")
+      assert_equal("rbaz", s)
+    end
+  end
+
+  def test_readpartial_error
+    pipe do |r, w|
+      s = ""
+      t = Thread.new { r.readpartial(5, s) }
+      0 until s.size == 5
+      s.clear
+      w.write "foobarbaz"
+      w.close
+      assert_raise(RuntimeError) { t.join }
+    end
+  end
+
+  def test_read
+    pipe do |r, w|
+      w.write "foobarbaz"
+      w.close
+      assert_raise(ArgumentError) { r.read(-1) }
+      assert_equal("fooba", r.read(5))
+      r.read(nil, s = "")
+      assert_equal("rbaz", s)
+    end
+  end
+
+  def test_read_error
+    pipe do |r, w|
+      s = ""
+      t = Thread.new { r.read(5, s) }
+      0 until s.size == 5
+      s.clear
+      w.write "foobarbaz"
+      w.close
+      assert_raise(RuntimeError) { t.join }
+    end
+  end
+
+  def test_write_nonblock
+    pipe do |r, w|
+      w.write_nonblock(1)
+      w.close
+      assert_equal("1", r.read)
+    end
+  end
+
+  def test_gets
+    pipe do |r, w|
+      w.write "foobarbaz"
+      w.close
+      assert_equal("", r.gets(0))
+      assert_equal("foobarbaz", r.gets(9))
+    end
+  end
+
+  def test_close_read
+    ruby do |f|
+      f.close_read
+      f.write "foobarbaz"
+      assert_raise(IOError) { f.read }
+    end
+  end
+
+  def test_close_read_pipe
+    pipe do |r, w|
+      r.close_read
+      assert_raise(Errno::EPIPE) { w.write "foobarbaz" }
+    end
+  end
+
+  def test_close_read_security_error
+    pipe do |r, w|
+      assert_raise(SecurityError) do
+        safe_4 { r.close_read }
+      end
+    end
+  end
+
+  def test_close_read_non_readable
+    pipe do |r, w|
+      assert_raise(IOError) do
+        w.close_read
+      end
+    end
+  end
+
+  def test_close_write
+    ruby do |f|
+      f.write "foobarbaz"
+      f.close_write
+      assert_equal("foobarbaz", f.read)
+    end
+  end
+
+  def test_close_write_security_error
+    pipe do |r, w|
+      assert_raise(SecurityError) do
+        safe_4 { r.close_write }
+      end
+    end
+  end
+
+  def test_close_write_non_readable
+    pipe do |r, w|
+      assert_raise(IOError) do
+        r.close_write
+      end
+    end
+  end
+
+  def test_pid
+    r, w = IO.pipe
+    assert_equal(nil, r.pid)
+    assert_equal(nil, w.pid)
+
+    pipe = IO.popen(EnvUtil.rubybin, "r+")
+    pid1 = pipe.pid
+    pipe.puts "p $$"
+    pipe.close_write
+    pid2 = pipe.read.chomp.to_i
+    assert_equal(pid2, pid1)
+    assert_equal(pid2, pipe.pid)
+    pipe.close
+    assert_raise(IOError) { pipe.pid }
+  end
+
+  def make_tempfile
+    t = Tempfile.new("foo")
+    t.puts "foo"
+    t.puts "bar"
+    t.puts "baz"
+    t.close
+    t
+  end
+
+  def test_set_lineno
+    t = make_tempfile
+
+    ruby("-e", <<-SRC, t.path) do |f|
+      open(ARGV[0]) do |f|
+        p $.
+        f.gets; p $.
+        f.gets; p $.
+        f.lineno = 1000; p $.
+        f.gets; p $.
+        f.gets; p $.
+        f.rewind; p $.
+        f.gets; p $.
+        f.gets; p $.
+        f.gets; p $.
+        f.gets; p $.
+      end
+    SRC
+      assert_equal("nil,1,2,2,1001,1001,1001,1,2,3,3", f.read.chomp.gsub("\n", ","))
+    end
+
+    pipe do |r, w|
+      w.puts "foo"
+      w.puts "bar"
+      w.puts "baz"
+      w.close
+      r.gets; assert_equal(1, $.)
+      r.gets; assert_equal(2, $.)
+      r.lineno = 1000; assert_equal(2, $.)
+      r.gets; assert_equal(1001, $.)
+      r.gets; assert_equal(1001, $.)
+    end
+  end
+
+  def test_readline
+    pipe do |r, w|
+      w.puts "foo"
+      w.puts "bar"
+      w.puts "baz"
+      w.close
+      r.readline; assert_equal(1, $.)
+      r.readline; assert_equal(2, $.)
+      r.lineno = 1000; assert_equal(2, $.)
+      r.readline; assert_equal(1001, $.)
+      assert_raise(EOFError) { r.readline }
+    end
+  end
+
+  def test_each_char
+    pipe do |r, w|
+      w.puts "foo"
+      w.puts "bar"
+      w.puts "baz"
+      w.close
+      a = []
+      r.each_char {|c| a << c }
+      assert_equal(%w(f o o) + ["\n"] + %w(b a r) + ["\n"] + %w(b a z) + ["\n"], a)
+    end
+  end
+
+  def test_lines
+    pipe do |r, w|
+      w.puts "foo"
+      w.puts "bar"
+      w.puts "baz"
+      w.close
+      e = r.lines
+      assert_equal("foo\n", e.next)
+      assert_equal("bar\n", e.next)
+      assert_equal("baz\n", e.next)
+      assert_raise(StopIteration) { e.next }
+    end
+  end
+
+  def test_bytes
+    pipe do |r, w|
+      w.puts "foo"
+      w.puts "bar"
+      w.puts "baz"
+      w.close
+      e = r.bytes
+      (%w(f o o) + ["\n"] + %w(b a r) + ["\n"] + %w(b a z) + ["\n"]).each do |c|
+        assert_equal(c.ord, e.next)
+      end
+      assert_raise(StopIteration) { e.next }
+    end
+  end
+
+  def test_chars
+    pipe do |r, w|
+      w.puts "foo"
+      w.puts "bar"
+      w.puts "baz"
+      w.close
+      e = r.chars
+      (%w(f o o) + ["\n"] + %w(b a r) + ["\n"] + %w(b a z) + ["\n"]).each do |c|
+        assert_equal(c, e.next)
+      end
+      assert_raise(StopIteration) { e.next }
+    end
+  end
+
+  def test_readbyte
+    pipe do |r, w|
+      w.puts "foo"
+      w.puts "bar"
+      w.puts "baz"
+      w.close
+      (%w(f o o) + ["\n"] + %w(b a r) + ["\n"] + %w(b a z) + ["\n"]).each do |c|
+        assert_equal(c.ord, r.readbyte)
+      end
+      assert_raise(EOFError) { r.readbyte }
+    end
+  end
+
+  def test_readchar
+    pipe do |r, w|
+      w.puts "foo"
+      w.puts "bar"
+      w.puts "baz"
+      w.close
+      (%w(f o o) + ["\n"] + %w(b a r) + ["\n"] + %w(b a z) + ["\n"]).each do |c|
+        assert_equal(c, r.readchar)
+      end
+      assert_raise(EOFError) { r.readchar }
+    end
+  end
+
+  def test_close_on_exec
+    # xxx
+    ruby do |f|
+      assert_equal(false, f.close_on_exec?)
+      f.close_on_exec = true
+      assert_equal(true, f.close_on_exec?)
+      f.close_on_exec = false
+      assert_equal(false, f.close_on_exec?)
+    end
+
+    pipe do |r, w|
+      assert_equal(false, r.close_on_exec?)
+      r.close_on_exec = true
+      assert_equal(true, r.close_on_exec?)
+      r.close_on_exec = false
+      assert_equal(false, r.close_on_exec?)
+
+      assert_equal(false, w.close_on_exec?)
+      w.close_on_exec = true
+      assert_equal(true, w.close_on_exec?)
+      w.close_on_exec = false
+      assert_equal(false, w.close_on_exec?)
+    end
+  end
+
+  def test_close_security_error
+    pipe do |r, w|
+      assert_raise(SecurityError) do
+        safe_4 { r.close }
+      end
+    end
+  end
+
+  def test_sysseek
+    t = make_tempfile
+
+    open(t.path) do |f|
+      f.sysseek(-4, IO::SEEK_END)
+      assert_equal("baz\n", f.read)
+    end
+
+    open(t.path) do |f|
+      a = [f.getc, f.getc, f.getc]
+      a.reverse_each {|c| f.ungetc c }
+      assert_raise(IOError) { f.sysseek(1) }
+    end
+  end
+
+  def test_syswrite
+    t = make_tempfile
+
+    open(t.path, "w") do |f|
+      o = Object.new
+      def o.to_s; "FOO\n"; end
+      f.syswrite(o)
+    end
+    assert_equal("FOO\n", File.read(t.path))
+  end
+
+  def test_sysread
+    t = make_tempfile
+
+    open(t.path) do |f|
+      a = [f.getc, f.getc, f.getc]
+      a.reverse_each {|c| f.ungetc c }
+      assert_raise(IOError) { f.sysread(1) }
+    end
+  end
+
+  def test_flag
+    t = make_tempfile
+
+    assert_raise(ArgumentError) do
+      open(t.path, "z") { }
+    end
+
+    assert_raise(ArgumentError) do
+      open(t.path, "rr") { }
+    end
+  end
+
+  def test_sysopen
+    t = make_tempfile
+    
+    fd = IO.sysopen(t.path)
+    assert_kind_of(Integer, fd)
+    f = IO.for_fd(fd)
+    assert_equal("foo\nbar\nbaz\n", f.read)
+    f.close
+    
+    fd = IO.sysopen(t.path, "w", 0666)
+    assert_kind_of(Integer, fd)
+    f = IO.for_fd(fd)
+    f.write("FOO\n")
+    f.close
+    
+    fd = IO.sysopen(t.path, "r")
+    assert_kind_of(Integer, fd)
+    f = IO.for_fd(fd)
+    assert_equal("FOO\n", f.read)
+    f.close
+  end
+
+  def test_open_redirect
+    o = Object.new
+    def o.to_open; self; end
+    assert_equal(o, open(o))
+    o2 = nil
+    open(o) do |f|
+      o2 = f
+    end
+    assert_equal(o, o2)
+  end
+
+  def test_open_pipe
+    open("|" + EnvUtil.rubybin, "r+") do |f|
+      f.puts "puts 'foo'"
+      f.close_write
+      assert_equal("foo\n", f.read)
+    end
+  end
+
+  def test_reopen
+    t = make_tempfile
+
+    pipe do |r, w|
+      assert_raise(SecurityError) do
+        safe_4 { r.reopen(t.path) }
+      end
+    end
+  end
+
+  def test_foreach
+    a = []
+    IO.foreach("|" + EnvUtil.rubybin + " -e 'puts :foo; puts :bar; puts :baz'") {|x| a << x }
+    assert_equal(["foo\n", "bar\n", "baz\n"], a)
+
+    t = make_tempfile
+
+    a = []
+    IO.foreach(t.path, {:mode => "r" }) {|x| a << x }
+    assert_equal(["foo\n", "bar\n", "baz\n"], a)
+
+    a = []
+    IO.foreach(t.path, {:open_args => [] }) {|x| a << x }
+    assert_equal(["foo\n", "bar\n", "baz\n"], a)
+
+    a = []
+    IO.foreach(t.path, {:open_args => ["r"] }) {|x| a << x }
+    assert_equal(["foo\n", "bar\n", "baz\n"], a)
+  end
+
+  def test_printf
+    pipe do |r, w|
+      printf(w, "foo %s baz\n", "bar")
+      w.close_write
+      assert_equal("foo bar baz\n", r.read)
+    end
+  end
+
+  def test_print
+    t = make_tempfile
+
+    EnvUtil.rubyexec("-", t.path) do |w, r, e|
+      w.puts "print while $<.gets"
+      w.close
+      assert_equal("", e.read)
+      assert_equal("foo\nbar\nbaz\n", r.read)
+    end
+  end
+
+  def test_putc
+    pipe do |r, w|
+      w.putc "A"
+      w.putc "BC"
+      w.putc 68
+      w.close_write
+      assert_equal("ABD", r.read)
+    end
+
+    EnvUtil.rubyexec do |w, r, e|
+      w.puts "putc 65"
+      w.close
+      assert_equal("", e.read)
+      assert_equal("A", r.read)
+    end
+  end
+
+  def test_puts_recursive_array
+    a = ["foo"]
+    a << a
+    pipe do |r, w|
+      w.puts a
+      w.close
+      assert_equal("foo\n[...]\n", r.read)
+    end
+  end
+
+  def test_display
+    pipe do |r, w|
+      "foo".display(w)
+      w.close
+      assert_equal("foo", r.read)
+    end
+
+    EnvUtil.rubyexec do |w, r, e|
+      w.puts "'foo'.display"
+      w.close
+      assert_equal("", e.read)
+      assert_equal("foo", r.read)
+    end
+  end
+
+  def test_set_stdout
+    assert_raise(TypeError) { $> = Object.new }
+
+    EnvUtil.rubyexec do |w, r, e|
+      w.puts "$> = $stderr"
+      w.puts "puts 'foo'"
+      w.close
+      assert_equal("foo\n", e.read)
+      assert_equal("", r.read)
+    end
+  end
+
+  def test_initialize
+    t = make_tempfile
+    
+    fd = IO.sysopen(t.path)
+    assert_kind_of(Integer, fd)
+    f = IO.new(fd, "w")
+    f.write("FOO\n")
+    f.close
+
+    assert_equal("foo\nbar\nbaz\n", File.read(t.path))
+
+    pipe do |r, w|
+      assert_raise(RuntimeError) do
+        o = Object.new
+        class << o; self; end.instance_eval do
+          define_method(:to_io) { r }
+        end
+        w.instance_eval { initialize(o) }
+      end
+    end
+
+    pipe do |r, w|
+      r, w = IO.new(r), IO.new(w)
+      w.puts "foo"
+      w.puts "bar"
+      w.puts "baz"
+      w.close
+      assert_equal("foo\nbar\nbaz\n", r.read)
+    end
+
+    pipe do |r, w|
+      assert_raise(ArgumentError) { IO.new(r, "r+") }
+    end
+
+    f = open(t.path)
+    assert_raise(RuntimeError) do
+      f.instance_eval { initialize }
+    end
+  end
+  
+  def test_new_with_block
+    EnvUtil.rubyexec do |w, r, e|
+      w.puts "r, w = IO.pipe"
+      w.puts "IO.new(r) {}"
+      w.close
+      assert_not_equal("", e.read)
+      assert_equal("", r.read)
+    end
+  end
+
+  def test_readline2
+    EnvUtil.rubyexec("-e", <<-SRC) do |w, r, e|
+      puts readline
+      puts readline
+      puts readline
+      begin
+        puts readline
+      rescue EOFError
+        puts "end"
+      end
+    SRC
+      w.puts "foo"
+      w.puts "bar"
+      w.puts "baz"
+      w.close
+      assert_equal("", e.read)
+      assert_equal("foo\nbar\nbaz\nend\n", r.read)
+    end
+  end
+
+  def test_readlines
+    EnvUtil.rubyexec("-e", "p readlines") do |w, r, e|
+      w.puts "foo"
+      w.puts "bar"
+      w.puts "baz"
+      w.close
+      assert_equal("", e.read)
+      assert_equal("[\"foo\\n\", \"bar\\n\", \"baz\\n\"]\n", r.read)
+    end
+  end
+
+  def test_s_read
+    t = make_tempfile
+
+    assert_equal("bar\n", File.read(t.path, 4, 4))
+  end
+
+  def test_uninitialized
+    assert_raise(IOError) { IO.allocate.print "" }
+  end
 end

Copied: MacRuby/branches/testing/test/ruby/test_iso_8859.rb (from rev 248, MacRuby/trunk/test/ruby/test_iso_8859.rb)
===================================================================
--- MacRuby/branches/testing/test/ruby/test_iso_8859.rb	                        (rev 0)
+++ MacRuby/branches/testing/test/ruby/test_iso_8859.rb	2008-06-05 08:33:02 UTC (rev 249)
@@ -0,0 +1,163 @@
+require 'test/unit'
+
+class TestISO8859 < Test::Unit::TestCase
+  ASSERTS = %q(
+    assert_match(/^(\xdf)\1$/i, "\xdf\xdf")
+    assert_match(/^(\xdf)\1$/i, "ssss")
+    # assert_match(/^(\xdf)\1$/i, "\xdfss") # this must be bug...
+    assert_match(/^[\xdfz]+$/i, "sszzsszz")
+    assert_match(/^SS$/i, "\xdf")
+    assert_match(/^Ss$/i, "\xdf")
+    ((0xc0..0xde).to_a - [0xd7]).each do |c|
+      c1 = c.chr("ENCODING")
+      c2 = (c + 0x20).chr("ENCODING")
+      assert_match(/^(#{ c1 })\1$/i, c2 + c1)
+      assert_match(/^(#{ c2 })\1$/i, c1 + c2)
+      assert_match(/^[#{ c1 }]+$/i, c2 + c1)
+      assert_match(/^[#{ c2 }]+$/i, c1 + c2)
+    end
+    assert_match(/^\xff$/i, "\xff")
+  )
+
+  def test_iso_8859_1
+    eval("# encoding: iso8859-1\n" + ASSERTS.gsub(/ENCODING/m, "iso8859-1"))
+  end
+
+  def test_iso_8859_2
+    eval("# encoding: iso8859-2\n" + ASSERTS.gsub(/ENCODING/m, "iso8859-2"))
+  end
+
+  def test_iso_8859_3
+    eval(%q(# encoding: iso8859-3
+      assert_match(/^(\xdf)\1$/i, "\xdf\xdf")
+      assert_match(/^(\xdf)\1$/i, "ssss")
+      assert_match(/^[\xdfz]+$/i, "sszzsszz")
+      assert_match(/^SS$/i, "\xdf")
+      assert_match(/^Ss$/i, "\xdf")
+      [0xa1, 0xa6, *(0xa9..0xac), 0xaf].each do |c|
+        c1 = c.chr("iso8859-3")
+        c2 = (c + 0x10).chr("iso8859-3")
+        assert_match(/^(#{ c1 })\1$/i, c2 + c1)
+        assert_match(/^(#{ c2 })\1$/i, c1 + c2)
+        assert_match(/^[#{ c1 }]+$/i, c2 + c1)
+        assert_match(/^[#{ c2 }]+$/i, c1 + c2)
+      end
+      ([*(0xc0..0xde)] - [0xc3, 0xd0, 0xd7]).each do |c|
+        c1 = c.chr("iso8859-3")
+        c2 = (c + 0x20).chr("iso8859-3")
+        assert_match(/^(#{ c1 })\1$/i, c2 + c1)
+        assert_match(/^(#{ c2 })\1$/i, c1 + c2)
+        assert_match(/^[#{ c1 }]+$/i, c2 + c1)
+        assert_match(/^[#{ c2 }]+$/i, c1 + c2)
+      end
+    ))
+  end
+
+  def test_iso_8859_4
+    eval("# encoding: iso8859-4\n" + ASSERTS.gsub(/ENCODING/m, "iso8859-4"))
+  end
+
+  def test_iso_8859_5
+    eval(%q(# encoding: iso8859-5
+      (0xb0..0xcf).each do |c|
+        c1 = c.chr("iso8859-5")
+        c2 = (c + 0x20).chr("iso8859-5")
+        assert_match(/^(#{ c1 })\1$/i, c2 + c1)
+        assert_match(/^(#{ c2 })\1$/i, c1 + c2)
+        assert_match(/^[#{ c1 }]+$/i, c2 + c1)
+        assert_match(/^[#{ c2 }]+$/i, c1 + c2)
+      end
+      ((0xa1..0xaf).to_a - [0xad]).each do |c|
+        c1 = c.chr("iso8859-5")
+        c2 = (c + 0x50).chr("iso8859-5")
+        assert_match(/^(#{ c1 })\1$/i, c2 + c1)
+        assert_match(/^(#{ c2 })\1$/i, c1 + c2)
+        assert_match(/^[#{ c1 }]+$/i, c2 + c1)
+        assert_match(/^[#{ c2 }]+$/i, c1 + c2)
+      end
+    ))
+  end
+
+  def test_iso_8859_6
+    eval(%q(# encoding: iso8859-6
+      [0xa4, 0xac, 0xbb, 0xbf, *(0xc1..0xda), *(0xe0..0xf2)].each do |c|
+        c1 = c.chr("iso8859-6")
+        assert_match(/^(#{ c1 })\1$/i, c1 * 2)
+      end
+    ))
+  end
+
+  def test_iso_8859_7
+    eval(%q(# encoding: iso8859-7
+      ((0xa0..0xfe).to_a - [0xae, 0xd2]).each do |c|
+        c1 = c.chr("iso8859-7")
+        assert_match(/^(#{ c1 })\1$/i, c1 * 2)
+      end
+      ((0xc1..0xd9).to_a - [0xd2]).each do |c|
+        c1 = c.chr("iso8859-7")
+        c2 = (c + 0x20).chr("iso8859-7")
+        assert_match(/^(#{ c1 })\1$/i, c2 + c1)
+        assert_match(/^(#{ c2 })\1$/i, c1 + c2)
+        assert_match(/^[#{ c1 }]+$/i, c2 + c1)
+        assert_match(/^[#{ c2 }]+$/i, c1 + c2)
+      end
+    ))
+  end
+
+  def test_iso_8859_8
+    eval(%q(# encoding: iso8859-8
+      [0xa0, *(0xa2..0xbe), *(0xdf..0xfa), 0xfc, 0xfd].each do |c|
+        c1 = c.chr("iso8859-8")
+        assert_match(/^(#{ c1 })\1$/i, c1 * 2)
+      end
+    ))
+  end
+
+  def test_iso_8859_9
+    eval(%q(# encoding: iso8859-9
+      assert_match(/^(\xdf)\1$/i, "\xdf\xdf")
+      assert_match(/^(\xdf)\1$/i, "ssss")
+      assert_match(/^[\xdfz]+$/i, "sszzsszz")
+      assert_match(/^SS$/i, "\xdf")
+      assert_match(/^Ss$/i, "\xdf")
+      ([*(0xc0..0xdc)] - [0xd7]).each do |c|
+        c1 = c.chr("iso8859-9")
+        c2 = (c + 0x20).chr("iso8859-9")
+        assert_match(/^(#{ c1 })\1$/i, c2 + c1)
+        assert_match(/^(#{ c2 })\1$/i, c1 + c2)
+        assert_match(/^[#{ c1 }]+$/i, c2 + c1)
+        assert_match(/^[#{ c2 }]+$/i, c1 + c2)
+      end
+    ))
+  end
+
+  def test_iso_8859_10
+    eval("# encoding: iso8859-10\n" + ASSERTS.gsub(/ENCODING/m, "iso8859-10"))
+  end
+
+  def test_iso_8859_11
+    eval(%q(# encoding: iso8859-11
+      [*(0xa0..0xda), *(0xdf..0xfb)].each do |c|
+        c1 = c.chr("iso8859-11")
+        assert_match(/^(#{ c1 })\1$/i, c1 * 2)
+      end
+    ))
+  end
+
+  def test_iso_8859_13
+    eval("# encoding: iso8859-13\n" + ASSERTS.gsub(/ENCODING/m, "iso8859-13"))
+  end
+
+  def test_iso_8859_14
+    eval("# encoding: iso8859-14\n" + ASSERTS.gsub(/ENCODING/m, "iso8859-14"))
+  end
+
+  def test_iso_8859_15
+    eval("# encoding: iso8859-15\n" + ASSERTS.gsub(/ENCODING/m, "iso8859-15"))
+  end
+
+  def test_iso_8859_16
+    eval("# encoding: iso8859-16\n" + ASSERTS.gsub(/ENCODING/m, "iso8859-16"))
+  end
+end
+

Copied: MacRuby/branches/testing/test/ruby/test_koi8.rb (from rev 248, MacRuby/trunk/test/ruby/test_koi8.rb)
===================================================================
--- MacRuby/branches/testing/test/ruby/test_koi8.rb	                        (rev 0)
+++ MacRuby/branches/testing/test/ruby/test_koi8.rb	2008-06-05 08:33:02 UTC (rev 249)
@@ -0,0 +1,22 @@
+require "test/unit"
+
+class TestKOI8 < Test::Unit::TestCase
+  ASSERTS = %q(
+    (0xc0..0xdf).each do |c|
+      c1 = c.chr("ENCODING")
+      c2 = (c + 0x20).chr("ENCODING")
+      assert_match(/^(#{ c1 })\1$/i, c2 + c1)
+      assert_match(/^(#{ c2 })\1$/i, c1 + c2)
+      assert_match(/^[#{ c1 }]+$/i, c2 + c1)
+      assert_match(/^[#{ c2 }]+$/i, c1 + c2)
+    end
+  )
+
+  def test_koi8_r
+    eval("# encoding: koi8-r\n" + ASSERTS.gsub("ENCODING", "koi8-r"))
+  end
+
+  def test_koi8_u
+    eval("# encoding: koi8-u\n" + ASSERTS.gsub("ENCODING", "koi8-u"))
+  end
+end

Modified: MacRuby/branches/testing/test/ruby/test_m17n.rb
===================================================================
--- MacRuby/branches/testing/test/ruby/test_m17n.rb	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/test/ruby/test_m17n.rb	2008-06-05 08:33:02 UTC (rev 249)
@@ -1233,4 +1233,13 @@
     s.setbyte(-4, 0x84)
     assert_equal(u("\xE3\x81\x84\xE3\x81\x84"), s)
   end
+
+  def test_compatible
+    assert_equal(nil, Encoding.compatible?("",0), "moved from btest/knownbug")
+  end
+
+  def test_force_encoding
+    assert(("".center(1, "\x80".force_encoding("utf-8")); true),
+           "moved from btest/knownbug, [ruby-dev:33807]")
+  end
 end

Modified: MacRuby/branches/testing/test/ruby/test_method.rb
===================================================================
--- MacRuby/branches/testing/test/ruby/test_method.rb	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/test/ruby/test_method.rb	2008-06-05 08:33:02 UTC (rev 249)
@@ -220,4 +220,14 @@
   def test_caller_negative_level
     assert_raise(ArgumentError) { caller(-1) }
   end
+
+  def test_attrset_ivar
+    c = Class.new
+    c.class_eval { attr_accessor :foo }
+    o = c.new
+    o.method(:foo=).call(42)
+    assert_equal(42, o.foo)
+    assert_raise(ArgumentError) { o.method(:foo=).call(1, 2, 3) }
+    assert_raise(ArgumentError) { o.method(:foo).call(1) }
+  end
 end

Modified: MacRuby/branches/testing/test/ruby/test_module.rb
===================================================================
--- MacRuby/branches/testing/test/ruby/test_module.rb	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/test/ruby/test_module.rb	2008-06-05 08:33:02 UTC (rev 249)
@@ -68,6 +68,10 @@
     list.reject {|c| c == PP::ObjectMixin }
   end
 
+  def remove_json_mixins(list)
+    list.reject {|c| c.to_s.start_with?("JSON") }
+  end
+
   module Mixin
     MIXIN = 1
     def mixin
@@ -194,9 +198,10 @@
     assert_equal([User, Mixin],      User.ancestors)
     assert_equal([Mixin],            Mixin.ancestors)
 
-    assert_equal([Object, Kernel, BasicObject], remove_pp_mixins(Object.ancestors))
+    assert_equal([Object, Kernel, BasicObject],
+                 remove_json_mixins(remove_pp_mixins(Object.ancestors)))
     assert_equal([String, Comparable, Object, Kernel, BasicObject],
-                 remove_pp_mixins(String.ancestors))
+                 remove_json_mixins(remove_pp_mixins(String.ancestors)))
   end
 
   def test_class_eval
@@ -242,9 +247,10 @@
   def test_included_modules
     assert_equal([], Mixin.included_modules)
     assert_equal([Mixin], User.included_modules)
-    assert_equal([Kernel], remove_pp_mixins(Object.included_modules))
+    assert_equal([Kernel],
+                 remove_json_mixins(remove_pp_mixins(Object.included_modules)))
     assert_equal([Comparable, Kernel],
-                 remove_pp_mixins(String.included_modules))
+                 remove_json_mixins(remove_pp_mixins(String.included_modules)))
   end
 
   def test_instance_methods
@@ -690,4 +696,23 @@
     o.extend(m2)
     assert_equal(true, o.respond_to?(:foo))
   end
+
+  def test_cyclic_include
+    m1 = Module.new
+    m2 = Module.new
+    m1.instance_eval { include(m2) }
+    assert_raise(ArgumentError) do
+      m2.instance_eval { include(m1) }
+    end
+  end
+
+  def test_include_p
+    m = Module.new
+    c1 = Class.new
+    c1.instance_eval { include(m) }
+    c2 = Class.new(c1)
+    assert_equal(true, c1.include?(m))
+    assert_equal(true, c2.include?(m))
+    assert_equal(false, m.include?(m))
+  end
 end

Modified: MacRuby/branches/testing/test/ruby/test_numeric.rb
===================================================================
--- MacRuby/branches/testing/test/ruby/test_numeric.rb	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/test/ruby/test_numeric.rb	2008-06-05 08:33:02 UTC (rev 249)
@@ -60,9 +60,9 @@
       def %(x); :mod; end
     end
 
-    assert_equal(42, DummyNumeric.new.div(0))
-    assert_equal(:mod, DummyNumeric.new.modulo(0))
-    assert_equal([42, :mod], DummyNumeric.new.divmod(0))
+    assert_equal(42, DummyNumeric.new.div(1))
+    assert_equal(:mod, DummyNumeric.new.modulo(1))
+    assert_equal([42, :mod], DummyNumeric.new.divmod(1))
 
     assert_kind_of(Integer, 11.divmod(3.5).first, '[ruby-dev:34006]')
 

Modified: MacRuby/branches/testing/test/ruby/test_objc.rb
===================================================================
--- MacRuby/branches/testing/test/ruby/test_objc.rb	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/test/ruby/test_objc.rb	2008-06-05 08:33:02 UTC (rev 249)
@@ -94,11 +94,15 @@
   def test_struct_create
     p = NSPoint.new
     assert_kind_of(NSPoint, p)
+    assert_kind_of(Float, p.x)
     assert_equal(0.0, p.x)
+    assert_kind_of(Float, p.y)
     assert_equal(0.0, p.y)
 
     p = NSPoint.new(1, 2)
+    assert_kind_of(Float, p.x)
     assert_equal(1.0, p.x)
+    assert_kind_of(Float, p.y)
     assert_equal(2.0, p.y)
 
     assert_raise(ArgumentError) { NSPoint.new(1) }

Modified: MacRuby/branches/testing/test/ruby/test_objectspace.rb
===================================================================
--- MacRuby/branches/testing/test/ruby/test_objectspace.rb	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/test/ruby/test_objectspace.rb	2008-06-05 08:33:02 UTC (rev 249)
@@ -47,5 +47,10 @@
     assert(h.values.all? {|x| x.is_a?(Integer) })
 
     assert_raise(TypeError) { ObjectSpace.count_objects(1) }
+
+    h0 = {:T_FOO=>1000}
+    h = ObjectSpace.count_objects(h0)
+    assert_same(h0, h)
+    assert_equal(0, h0[:T_FOO])
   end
 end

Modified: MacRuby/branches/testing/test/ruby/test_pack.rb
===================================================================
--- MacRuby/branches/testing/test/ruby/test_pack.rb	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/test/ruby/test_pack.rb	2008-06-05 08:33:02 UTC (rev 249)
@@ -441,4 +441,8 @@
       end.join
     end
   end
+
+  def test_length_too_big
+    assert_raise(RangeError) { [].pack("C100000000000000000000") }
+  end
 end

Modified: MacRuby/branches/testing/test/ruby/test_proc.rb
===================================================================
--- MacRuby/branches/testing/test/ruby/test_proc.rb	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/test/ruby/test_proc.rb	2008-06-05 08:33:02 UTC (rev 249)
@@ -210,6 +210,18 @@
     assert_equal(fib, [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89])
   end
 
+  def test_curry_from_knownbug
+    a = lambda {|x, y, &b| b }
+    b = a.curry[1]
+
+    assert_equal(:ok,
+      if b.call(2){} == nil
+        :ng
+      else
+        :ok
+      end, 'moved from btest/knownbug, [ruby-core:15551]')
+  end
+
   def test_dup_clone
     b = proc {|x| x + "bar" }
     class << b; attr_accessor :foo; end

Modified: MacRuby/branches/testing/test/ruby/test_process.rb
===================================================================
--- MacRuby/branches/testing/test/ruby/test_process.rb	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/test/ruby/test_process.rb	2008-06-05 08:33:02 UTC (rev 249)
@@ -697,7 +697,7 @@
         File.open("result2", "w") {|t| t << "taki pid=#{$$} ppid=#{Process.ppid}" }
         exit 8
       End
-      ret = system("#{RUBY} script1; #{RUBY} script2")
+      ret = system("#{RUBY} script1 || #{RUBY} script2")
       status = $?
       assert_equal(false, ret)
       assert(status.exited?)
@@ -719,7 +719,7 @@
         File.open("result2", "w") {|t| t << "take pid=#{$$} ppid=#{Process.ppid}" }
         exit 8
       End
-      pid = spawn("#{RUBY} script1; #{RUBY} script2")
+      pid = spawn("#{RUBY} script1 || #{RUBY} script2")
       Process.wait pid
       status = $?
       assert(status.exited?)
@@ -742,7 +742,7 @@
         puts "tika pid=#{$$} ppid=#{Process.ppid}"
         exit 8
       End
-      io = IO.popen("#{RUBY} script1; #{RUBY} script2")
+      io = IO.popen("#{RUBY} script1 || #{RUBY} script2")
       result = io.read
       io.close
       status = $?
@@ -765,7 +765,7 @@
       End
       write_file("s", <<-"End")
 	ruby = #{RUBY.dump}
-	exec("\#{ruby} script1; \#{ruby} script2")
+	exec("\#{ruby} script1 || \#{ruby} script2")
       End
       pid = spawn RUBY, "s"
       Process.wait pid

Modified: MacRuby/branches/testing/test/ruby/test_regexp.rb
===================================================================
--- MacRuby/branches/testing/test/ruby/test_regexp.rb	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/test/ruby/test_regexp.rb	2008-06-05 08:33:02 UTC (rev 249)
@@ -272,7 +272,7 @@
       Thread.new { $SAFE = 4; re.instance_eval { initialize(re) } }.join
     end
 
-    assert_equal(Encoding::ASCII_8BIT, Regexp.new("b..", nil, "n").encoding)
+    assert_equal(Encoding.find("ASCII-8BIT"), Regexp.new("b..", nil, "n").encoding)
     assert_equal("bar", "foobarbaz"[Regexp.new("b..", nil, "n")])
 
     assert_raise(RegexpError) { Regexp.new(")(") }
@@ -471,12 +471,12 @@
     ss = [ss] unless ss.is_a?(Array)
     ss.each do |e, s|
       s ||= e
+      assert_match(re, s)
       m = re.match(s)
-      assert_kind_of(MatchData, m)
       assert_equal(e, m[0])
     end
     fs = [fs] unless fs.is_a?(Array)
-    fs.each {|s| assert_nil(re.match(s)) }
+    fs.each {|s| assert_no_match(re, s) }
   end
 
   def failcheck(re)
@@ -512,8 +512,53 @@
     check(/\A\a\z/, "\007")
     check(/\A\e\z/, "\033")
     check(/\A\v\z/, "\v")
+    failcheck('(')
+    failcheck('(?foo)')
+    failcheck('/\p{foobarbazqux}/')
+    failcheck('/\p{foobarbazqux' + 'a' * 1000 + '}/')
+    failcheck('/[1-\w]/')
   end
 
+  def test_exec
+    check(/A*B/, %w(B AB AAB AAAB), %w(A))
+    check(/\w*!/, %w(! a! ab! abc!), %w(abc))
+    check(/\w*\W/, %w(! a" ab# abc$), %w(abc))
+    check(/\w*\w/, %w(z az abz abcz), %w(!))
+    check(/[a-z]*\w/, %w(z az abz abcz), %w(!))
+    check(/[a-z]*\W/, %w(! a" ab# abc$), %w(A))
+    check(/((a|bb|ccc|dddd)(1|22|333|4444))/i, %w(a1 bb1 a22), %w(a2 b1))
+    check(/\u0080/, (1..4).map {|i| ["\u0080", "\u0080" * i] }, ["\u0081"])
+    check(/\u0080\u0080/, (2..4).map {|i| ["\u0080" * 2, "\u0080" * i] }, ["\u0081"])
+    check(/\u0080\u0080\u0080/, (3..4).map {|i| ["\u0080" * 3, "\u0080" * i] }, ["\u0081"])
+    check(/\u0080\u0080\u0080\u0080/, (4..4).map {|i| ["\u0080" * 4, "\u0080" * i] }, ["\u0081"])
+    check(/[^\u3042\u3043\u3044]/, %W(a b \u0080 \u3041 \u3045), %W(\u3042 \u3043 \u3044))
+    check(/a.+/m, %W(a\u0080 a\u0080\u0080 a\u0080\u0080\u0080), %W(a))
+    check(/a.+z/m, %W(a\u0080z a\u0080\u0080z a\u0080\u0080\u0080z), %W(az))
+    check(/abc\B.\Bxyz/, %w(abcXxyz abc0xyz), %w(abc|xyz abc-xyz))
+    check(/\Bxyz/, [%w(xyz abcXxyz), %w(xyz abc0xyz)], %w(abc xyz abc-xyz))
+    check(/abc\B/, [%w(abc abcXxyz), %w(abc abc0xyz)], %w(abc xyz abc-xyz))
+    failcheck('(?<foo>abc)\1')
+    check(/^(A+|B+)(?>\g<1>)*[BC]$/, %w(AC BC ABC BAC AABBC), %w(AABB))
+    check(/^(A+|B(?>\g<1>)*)[AC]$/, %w(AAAC BBBAAAAC), %w(BBBAAA))
+    check(/^()(?>\g<1>)*$/, "", "a")
+    check(/^(?>(?=a)(#{ "a" * 1000 }|))++$/, ["a" * 1000, "a" * 2000, "a" * 3000], ["", "a" * 500, "b" * 1000])
+    check(eval('/^(?:a?)?$/'), ["", "a"], ["aa"])
+    check(eval('/^(?:a+)?$/'), ["", "a", "aa"], ["ab"])
+    check(/^(?:a?)+?$/, ["", "a", "aa"], ["ab"])
+    check(/^a??[ab]/, [["a", "a"], ["a", "aa"], ["b", "b"], ["a", "ab"]], ["c"])
+    check(/^(?:a*){3,5}$/, ["", "a", "aa", "aaa", "aaaa", "aaaaa", "aaaaaa"], ["b"])
+    check(/^(?:a+){3,5}$/, ["aaa", "aaaa", "aaaaa", "aaaaaa"], ["", "a", "aa", "b"])
+  end
+
+  def test_parse_look_behind
+    check(/(?<=A)B(?=C)/, [%w(B ABC)], %w(aBC ABc aBc))
+    check(/(?<!A)B(?!C)/, [%w(B aBc)], %w(ABC aBC ABc))
+    failcheck('(?<=.*)')
+    failcheck('(?<!.*)')
+    check(/(?<=A|B.)C/, [%w(C AC), %w(C BXC)], %w(C BC))
+    check(/(?<!A|B.)C/, [%w(C C), %w(C BC)], %w(AC BXC))
+  end
+
   def test_parse_kg
     check(/\A(.)(.)\k<1>(.)\z/, %w(abac abab ....), %w(abcd aaba xxx))
     check(/\A(.)(.)\k<-1>(.)\z/, %w(abbc abba ....), %w(abcd aaba xxx))
@@ -532,7 +577,22 @@
     failcheck('()\k<-2>')
     failcheck('()\g<-2>')
     check(/\A(?<x>.)(?<x>.)\k<x>\z/, %w(aba abb), %w(abc .. ....))
+    check(/\A(?<x>.)(?<x>.)\k<x>\z/i, %w(aba ABa abb ABb), %w(abc .. ....))
     check(/\k\g/, "kg")
+    failcheck('(.\g<1>)')
+    failcheck('(.\g<2>)')
+    failcheck('(?=\g<1>)')
+    failcheck('((?=\g<1>))')
+    failcheck('(\g<1>|.)')
+    failcheck('(.|\g<1>)')
+    check(/(!)(?<=(a)|\g<1>)/, ["!"], %w(a))
+    check(/^(a|b\g<1>c)$/, %w(a bac bbacc bbbaccc), %w(bbac bacc))
+    check(/^(a|b\g<2>c)(B\g<1>C){0}$/, %w(a bBaCc bBbBaCcCc bBbBbBaCcCcCc), %w(bBbBaCcC BbBaCcCc))
+    check(/\A(?<n>.|X\g<n>)(?<x>\g<n>){0}(?<y>\k<n+0>){0}\g<x>\g<y>\z/, "XXaXbXXa", %w(XXabXa abb))
+    check(/\A(?<n>.|X\g<n>)(?<x>\g<n>){0}(?<y>\k<n+1>){0}\g<x>\g<y>\z/, "XaXXbXXb", %w(aXXbXb aba))
+    failcheck('(?<x>)(?<x>)(\g<x>)')
+    check(/^(?<x>foo)(bar)\k<x>/, %w(foobarfoo), %w(foobar barfoo))
+    check(/^(?<a>f)(?<a>o)(?<a>o)(?<a>b)(?<a>a)(?<a>r)(?<a>b)(?<a>a)(?<a>z)\k<a>{9}$/, %w(foobarbazfoobarbaz foobarbazbazbarfoo foobarbazzabraboof), %w(foobar barfoo))
   end
 
   def test_parse_curly_brace
@@ -595,6 +655,7 @@
     check(/\A[a-f&&[^b-c]&&[^e]]\z/, %w(a d f), %w(b c e g 0))
     check(/\A[[^b-c]&&[^e]&&a-f]\z/, %w(a d f), %w(b c e g 0))
     check(/\A[\n\r\t]\z/, ["\n", "\r", "\t"])
+    failcheck('[9-1]')
   end
 
   def test_posix_bracket
@@ -608,4 +669,90 @@
     failcheck('[[:alpha:')
     failcheck('[[:alp:]]')
   end
+
+  def test_backward
+    assert_equal(3, "foobar".rindex(/b.r/i))
+    assert_equal(nil, "foovar".rindex(/b.r/i))
+    assert_equal(3, ("foo" + "bar" * 1000).rindex(/#{"bar"*1000}/))
+    assert_equal(4, ("foo\nbar\nbaz\n").rindex(/bar/i))
+  end
+
+  def test_uninitialized
+    assert_raise(TypeError) { Regexp.allocate.hash }
+    assert_raise(TypeError) { Regexp.allocate.eql? Regexp.allocate }
+    assert_raise(TypeError) { Regexp.allocate == Regexp.allocate }
+    assert_raise(TypeError) { Regexp.allocate =~ "" }
+    assert_equal(false, Regexp.allocate === Regexp.allocate)
+    assert_nil(~Regexp.allocate)
+    assert_raise(TypeError) { Regexp.allocate.match("") }
+    assert_raise(TypeError) { Regexp.allocate.to_s }
+    assert_raise(TypeError) { Regexp.allocate.inspect }
+    assert_raise(TypeError) { Regexp.allocate.source }
+    assert_raise(TypeError) { Regexp.allocate.casefold? }
+    assert_raise(TypeError) { Regexp.allocate.options }
+    assert_equal(Encoding.find("ASCII-8BIT"), Regexp.allocate.encoding)
+    assert_equal(false, Regexp.allocate.fixed_encoding?)
+    assert_raise(TypeError) { Regexp.allocate.names }
+    assert_raise(TypeError) { Regexp.allocate.named_captures }
+
+    assert_raise(TypeError) { MatchData.allocate.regexp }
+    assert_raise(TypeError) { MatchData.allocate.names }
+    assert_raise(TypeError) { MatchData.allocate.size }
+    assert_raise(TypeError) { MatchData.allocate.length }
+    assert_raise(TypeError) { MatchData.allocate.offset(0) }
+    assert_raise(TypeError) { MatchData.allocate.begin(0) }
+    assert_raise(TypeError) { MatchData.allocate.end(0) }
+    assert_raise(TypeError) { MatchData.allocate.to_a }
+    assert_raise(TypeError) { MatchData.allocate[:foo] }
+    assert_raise(TypeError) { MatchData.allocate.captures }
+    assert_raise(TypeError) { MatchData.allocate.values_at }
+    assert_raise(TypeError) { MatchData.allocate.pre_match }
+    assert_raise(TypeError) { MatchData.allocate.post_match }
+    assert_raise(TypeError) { MatchData.allocate.to_s }
+    assert_match(/^#<MatchData:.*>$/, MatchData.allocate.inspect)
+    assert_raise(TypeError) { MatchData.allocate.string }
+    $~ = MatchData.allocate
+    assert_raise(TypeError) { $& }
+    assert_raise(TypeError) { $` }
+    assert_raise(TypeError) { $' }
+    assert_raise(TypeError) { $+ }
+  end
+
+  def test_unicode
+    assert_match(/^\u3042{0}\p{Any}$/, "a")
+    assert_match(/^\u3042{0}\p{Any}$/, "\u3041")
+    assert_match(/^\u3042{0}\p{Any}$/, "\0")
+    assert_no_match(/^\u3042{0}\p{Any}$/, "\0\0")
+    assert_no_match(/^\u3042{0}\p{Any}$/, "")
+    assert_raise(SyntaxError) { eval('/^\u3042{0}\p{' + "\u3042" + '}$/') }
+    assert_raise(SyntaxError) { eval('/^\u3042{0}\p{' + 'a' * 1000 + '}$/') }
+    assert_raise(SyntaxError) { eval('/^\u3042{0}\p{foobarbazqux}$/') }
+    assert_match(/^(\uff21)(a)\1\2$/i, "\uff21A\uff41a")
+    assert_no_match(/^(\uff21)\1$/i, "\uff21A")
+    assert_no_match(/^(\uff41)\1$/i, "\uff41a")
+    assert_match(/^\u00df$/i, "\u00df")
+    assert_match(/^\u00df$/i, "ss")
+    #assert_match(/^(\u00df)\1$/i, "\u00dfss") # this must be bug...
+    assert_match(/^\u00df{2}$/i, "\u00dfss")
+    assert_match(/^\u00c5$/i, "\u00c5")
+    assert_match(/^\u00c5$/i, "\u00e5")
+    assert_match(/^\u00c5$/i, "\u212b")
+    assert_match(/^(\u00c5)\1\1$/i, "\u00c5\u00e5\u212b")
+    assert_match(/^\u0149$/i, "\u0149")
+    assert_match(/^\u0149$/i, "\u02bcn")
+    #assert_match(/^(\u0149)\1$/i, "\u0149\u02bcn") # this must be bug...
+    assert_match(/^\u0149{2}$/i, "\u0149\u02bcn")
+    assert_match(/^\u0390$/i, "\u0390")
+    assert_match(/^\u0390$/i, "\u03b9\u0308\u0301")
+    #assert_match(/^(\u0390)\1$/i, "\u0390\u03b9\u0308\u0301") # this must be bug...
+    assert_match(/^\u0390{2}$/i, "\u0390\u03b9\u0308\u0301")
+    assert_match(/^\ufb05$/i, "\ufb05")
+    assert_match(/^\ufb05$/i, "\ufb06")
+    assert_match(/^\ufb05$/i, "st")
+    #assert_match(/^(\ufb05)\1\1$/i, "\ufb05\ufb06st") # this must be bug...
+    assert_match(/^\ufb05{3}$/i, "\ufb05\ufb06st")
+    assert_match(/^\u03b9\u0308\u0301$/i, "\u0390")
+    assert_nothing_raised { 0x03ffffff.chr("utf-8").size }
+    assert_nothing_raised { 0x7fffffff.chr("utf-8").size }
+  end
 end

Copied: MacRuby/branches/testing/test/ruby/test_require.rb (from rev 248, MacRuby/trunk/test/ruby/test_require.rb)
===================================================================
--- MacRuby/branches/testing/test/ruby/test_require.rb	                        (rev 0)
+++ MacRuby/branches/testing/test/ruby/test_require.rb	2008-06-05 08:33:02 UTC (rev 249)
@@ -0,0 +1,235 @@
+require 'test/unit'
+
+require 'tempfile'
+require_relative 'envutil'
+
+class TestRequire < Test::Unit::TestCase
+  def ruby(*r, &b)
+    EnvUtil.rubyexec(*r, &b)
+  end
+
+  def test_require_invalid_shared_object
+    t = Tempfile.new(["test_ruby_test_require", ".so"])
+    t.puts "dummy"
+    t.close
+
+    ruby do |w, r, e|
+      w.puts "begin"
+      w.puts "  require \"#{ t.path }\""
+      w.puts "rescue LoadError"
+      w.puts "  p :ok"
+      w.puts "end"
+      w.close
+      assert_equal(":ok", r.read.chomp)
+    end
+  end
+
+  def test_require_too_long_filename
+    ruby do |w, r, e|
+      w.puts "begin"
+      w.puts "  require '#{ "foo/" * 10000 }foo'"
+      w.puts "rescue LoadError"
+      w.puts "  p :ok"
+      w.puts "end"
+      w.close
+      e.read
+      assert_equal(":ok", r.read.chomp)
+    end
+  end
+
+  def test_require_path_home
+    env_rubypath, env_home = ENV["RUBYPATH"], ENV["HOME"]
+
+    ENV["RUBYPATH"] = "~"
+    ENV["HOME"] = "/foo" * 10000
+    ruby("-S", "test_ruby_test_require") do |w, r, e|
+      w.close
+      e.read
+      assert_equal("", r.read)
+    end
+
+    ENV["RUBYPATH"] = "~" + "/foo" * 10000
+    ENV["HOME"] = "/foo"
+    ruby("-S", "test_ruby_test_require") do |w, r, e|
+      w.close
+      e.read
+      assert_equal("", r.read)
+    end
+
+    t = Tempfile.new(["test_ruby_test_require", ".rb"])
+    t.puts "p :ok"
+    t.close
+    ENV["RUBYPATH"] = "~"
+    ENV["HOME"], name = File.split(t.path)
+    ruby("-S", name) do |w, r, e|
+      w.close
+      assert_equal(":ok", r.read.chomp)
+      assert_equal("", e.read)
+    end
+
+  ensure
+    env_rubypath ? ENV["RUBYPATH"] = env_rubypath : ENV.delete("RUBYPATH")
+    env_home ? ENV["HOME"] = env_home : ENV.delete("HOME")
+  end
+
+  def test_define_class
+    begin
+      require "socket"
+    rescue LoadError
+      return
+    end
+
+    ruby do |w, r, e|
+      w.puts "BasicSocket = 1"
+      w.puts "begin"
+      w.puts "  require 'socket'"
+      w.puts "  p :ng"
+      w.puts "rescue TypeError"
+      w.puts "  p :ok"
+      w.puts "end"
+      w.close
+      assert_equal("", e.read)
+      assert_equal(":ok", r.read.chomp)
+    end
+
+    ruby do |w, r, e|
+      w.puts "class BasicSocket; end"
+      w.puts "begin"
+      w.puts "  require 'socket'"
+      w.puts "  p :ng"
+      w.puts "rescue NameError"
+      w.puts "  p :ok"
+      w.puts "end"
+      w.close
+      assert_equal("", e.read)
+      assert_equal(":ok", r.read.chomp)
+    end
+
+    ruby do |w, r, e|
+      w.puts "class BasicSocket < IO; end"
+      w.puts "begin"
+      w.puts "  require 'socket'"
+      w.puts "  p :ok"
+      w.puts "rescue Exception"
+      w.puts "  p :ng"
+      w.puts "end"
+      w.close
+      assert_equal("", e.read)
+      assert_equal(":ok", r.read.chomp)
+    end
+  end
+
+  def test_define_class_under
+    begin
+      require "zlib"
+    rescue LoadError
+      return
+    end
+
+    ruby do |w, r, e|
+      w.puts "module Zlib; end"
+      w.puts "Zlib::Error = 1"
+      w.puts "begin"
+      w.puts "  require 'zlib'"
+      w.puts "  p :ng"
+      w.puts "rescue TypeError"
+      w.puts "  p :ok"
+      w.puts "end"
+      w.close
+      assert_equal("", e.read)
+      assert_equal(":ok", r.read.chomp)
+    end
+
+    ruby do |w, r, e|
+      w.puts "module Zlib; end"
+      w.puts "class Zlib::Error; end"
+      w.puts "begin"
+      w.puts "  require 'zlib'"
+      w.puts "  p :ng"
+      w.puts "rescue NameError"
+      w.puts "  p :ok"
+      w.puts "end"
+      w.close
+      assert_equal("", e.read)
+      assert_equal(":ok", r.read.chomp)
+    end
+
+    ruby do |w, r, e|
+      w.puts "module Zlib; end"
+      w.puts "class Zlib::Error < StandardError; end"
+      w.puts "begin"
+      w.puts "  require 'zlib'"
+      w.puts "  p :ok"
+      w.puts "rescue Exception"
+      w.puts "  p :ng"
+      w.puts "end"
+      w.close
+      assert_equal("", e.read)
+      assert_equal(":ok", r.read.chomp)
+    end
+  end
+
+  def test_define_module
+    begin
+      require "zlib"
+    rescue LoadError
+      return
+    end
+
+    ruby do |w, r, e|
+      w.puts "Zlib = 1"
+      w.puts "begin"
+      w.puts "  require 'zlib'"
+      w.puts "  p :ng"
+      w.puts "rescue TypeError"
+      w.puts "  p :ok"
+      w.puts "end"
+      w.close
+      assert_equal("", e.read)
+      assert_equal(":ok", r.read.chomp)
+    end
+  end
+
+  def test_define_module_under
+    begin
+      require "socket"
+    rescue LoadError
+      return
+    end
+
+    ruby do |w, r, e|
+      w.puts "class BasicSocket < IO; end"
+      w.puts "class Socket < BasicSocket; end"
+      w.puts "Socket::Constants = 1"
+      w.puts "begin"
+      w.puts "  require 'socket'"
+      w.puts "  p :ng"
+      w.puts "rescue TypeError"
+      w.puts "  p :ok"
+      w.puts "end"
+      w.close
+      assert_equal("", e.read)
+      assert_equal(":ok", r.read.chomp)
+    end
+  end
+
+  def test_load
+    t = Tempfile.new(["test_ruby_test_require", ".rb"])
+    t.puts "module Foo; end"
+    t.puts "at_exit { p :wrap_end }"
+    t.puts "at_exit { raise 'error in at_exit test' }"
+    t.puts "p :ok"
+    t.close
+
+    ruby do |w, r, e|
+      w.puts "load(#{ t.path.dump }, true)"
+      w.puts "GC.start"
+      w.puts "p :end"
+      w.close
+      assert_match(/error in at_exit test/, e.read)
+      assert_equal(":ok\n:end\n:wrap_end", r.read.chomp)
+    end
+
+    assert_raise(ArgumentError) { at_exit }
+  end
+end

Modified: MacRuby/branches/testing/test/ruby/test_rubyoptions.rb
===================================================================
--- MacRuby/branches/testing/test/ruby/test_rubyoptions.rb	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/test/ruby/test_rubyoptions.rb	2008-06-05 08:33:02 UTC (rev 249)
@@ -84,7 +84,9 @@
 
   def test_verbose
     ruby('-vve', '') do |w, r, e|
-      assert_match(/^ruby #{RUBY_VERSION} .*? \[#{RUBY_PLATFORM}\]$/, r.read)
+      description = r.read
+      assert_match(/^ruby #{RUBY_VERSION} .*? \[#{RUBY_PLATFORM}\]$/, description)
+      assert_equal RUBY_DESCRIPTION, description.chomp
     end
 
     ruby('--verbose', '-e', 'p $VERBOSE') do |w, r, e|

Copied: MacRuby/branches/testing/test/ruby/test_shift_jis.rb (from rev 248, MacRuby/trunk/test/ruby/test_shift_jis.rb)
===================================================================
--- MacRuby/branches/testing/test/ruby/test_shift_jis.rb	                        (rev 0)
+++ MacRuby/branches/testing/test/ruby/test_shift_jis.rb	2008-06-05 08:33:02 UTC (rev 249)
@@ -0,0 +1,27 @@
+# vim: set fileencoding=shift_jis
+
+require "test/unit"
+
+class TestShiftJIS < Test::Unit::TestCase
+  def test_mbc_case_fold
+    assert_match(/(\x82\x81)(a)\1\2/i, "\x82\x81a\x82\x81A")
+    assert_no_match(/(\x82\x81)(a)\1\2/i, "\x82\x81a\x82`A")
+  end
+
+  def test_property
+    assert_match(/\x82\xA0{0}\p{Hiragana}{4}/, "\x82Ђ炪\x82\xC8")
+    assert_no_match(/\x82\xA0{0}\p{Hiragana}{4}/, "\x83J\x83^\x83J\x83i")
+    assert_no_match(/\x82\xA0{0}\p{Hiragana}{4}/, "\x8A\xBF\x8E\x9A\x8A\xBF\x8E\x9A")
+    assert_no_match(/\x82\xA0{0}\p{Katakana}{4}/, "\x82Ђ炪\x82\xC8")
+    assert_match(/\x82\xA0{0}\p{Katakana}{4}/, "\x83J\x83^\x83J\x83i")
+    assert_no_match(/\x82\xA0{0}\p{Katakana}{4}/, "\x8A\xBF\x8E\x9A\x8A\xBF\x8E\x9A")
+    assert_raise(RegexpError) { Regexp.new('\x82\xA0{0}\p{foobarbaz}') }
+  end
+
+  def test_code_to_mbclen
+    s = "\x82\xA0\x82\xA2\x82\xA4\x82\xA6\x82\xA8"
+    s << 0x82a9
+    assert_equal("\x82\xA0\x82\xA2\x82\xA4\x82\xA6\x82\xA8\x82\xA9", s)
+    assert_raise(ArgumentError) { s << 0x82 }
+  end
+end

Modified: MacRuby/branches/testing/test/ruby/test_signal.rb
===================================================================
--- MacRuby/branches/testing/test/ruby/test_signal.rb	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/test/ruby/test_signal.rb	2008-06-05 08:33:02 UTC (rev 249)
@@ -64,4 +64,103 @@
       w0.close
     end
   end
+
+  def test_invalid_signal_name
+    return unless Process.respond_to?(:kill)
+
+    assert_raise(ArgumentError) { Process.kill(:XXXXXXXXXX, $$) }
+  end
+
+  def test_signal_exception
+    assert_raise(ArgumentError) { SignalException.new }
+    assert_raise(ArgumentError) { SignalException.new(-1) }
+    assert_raise(ArgumentError) { SignalException.new(:XXXXXXXXXX) }
+    Signal.list.each do |signm, signo|
+      next if signm == "EXIT"
+      assert_equal(SignalException.new(signm).signo, signo)
+      assert_equal(SignalException.new(signm.to_sym).signo, signo)
+      assert_equal(SignalException.new(signo).signo, signo)
+    end
+  end
+
+  def test_interrupt
+    assert_raise(Interrupt) { raise Interrupt.new }
+  end
+
+  def test_signal2
+    return unless Process.respond_to?(:kill)
+    begin
+      x = false
+      oldtrap = Signal.trap(:INT) {|sig| x = true }
+      GC.start
+
+      assert_raise(ArgumentError) { Process.kill }
+
+      Timeout.timeout(10) do
+        x = false
+        Process.kill(SignalException.new(:INT).signo, $$)
+        nil until x
+
+        x = false
+        Process.kill("INT", $$)
+        nil until x
+
+        x = false
+        Process.kill("SIGINT", $$)
+        nil until x
+
+        x = false
+        o = Object.new
+        def o.to_str; "SIGINT"; end
+        Process.kill(o, $$)
+        nil until x
+      end
+
+      assert_raise(ArgumentError) { Process.kill(Object.new, $$) }
+
+    ensure
+      Signal.trap(:INT, oldtrap) if oldtrap
+    end
+  end
+
+  def test_trap
+    return unless Process.respond_to?(:kill)
+    begin
+      oldtrap = Signal.trap(:INT) {|sig| }
+
+      assert_raise(ArgumentError) { Signal.trap }
+
+      assert_raise(SecurityError) do
+        s = proc {}.taint
+        Signal.trap(:INT, s)
+      end
+
+      # FIXME!
+      Signal.trap(:INT, nil)
+      Signal.trap(:INT, "")
+      Signal.trap(:INT, "SIG_IGN")
+      Signal.trap(:INT, "IGNORE")
+
+      Signal.trap(:INT, "SIG_DFL")
+      Signal.trap(:INT, "SYSTEM_DEFAULT")
+
+      Signal.trap(:INT, "EXIT")
+
+      assert_raise(ArgumentError) { Signal.trap(:INT, "xxxxxx") }
+      assert_raise(ArgumentError) { Signal.trap(:INT, "xxxx") }
+
+      Signal.trap(SignalException.new(:INT).signo, "SIG_DFL")
+
+      assert_raise(ArgumentError) { Signal.trap(-1, "xxxx") }
+
+      o = Object.new
+      def o.to_str; "SIGINT"; end
+      Signal.trap(o, "SIG_DFL")
+
+      assert_raise(ArgumentError) { Signal.trap("XXXXXXXXXX", "SIG_DFL") }
+
+    ensure
+      Signal.trap(:INT, oldtrap) if oldtrap
+    end
+  end
 end

Modified: MacRuby/branches/testing/test/ruby/test_sprintf.rb
===================================================================
--- MacRuby/branches/testing/test/ruby/test_sprintf.rb	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/test/ruby/test_sprintf.rb	2008-06-05 08:33:02 UTC (rev 249)
@@ -185,6 +185,7 @@
   def test_float
     assert_equal("36893488147419111424",
                  sprintf("%20.0f", 36893488147419107329.0))
+    assert_equal(" Inf", sprintf("% 0e", 1.0/0.0), "moved from btest/knownbug")
   end
 
   BSIZ = 120

Modified: MacRuby/branches/testing/test/ruby/test_string.rb
===================================================================
--- MacRuby/branches/testing/test/ruby/test_string.rb	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/test/ruby/test_string.rb	2008-06-05 08:33:02 UTC (rev 249)
@@ -1,4 +1,5 @@
 require 'test/unit'
+require_relative 'envutil'
 
 # use of $= is deprecated after 1.7.1
 def pre_1_7_1
@@ -624,6 +625,8 @@
     a.taint
     assert(a.gsub(/./, S('X')).tainted?)
 
+    assert_equal("z", "abc".gsub(/./, "a" => "z"), "moved from btest/knownbug")
+
     assert_raise(ArgumentError) { "foo".gsub }
   end
 
@@ -653,6 +656,9 @@
 
     a = S("hello")
     assert_nil(a.sub!(S('X'), S('Y')))
+
+    a = S("hello").freeze
+    assert_raise(RuntimeError) { a.gsub!(/./, '') }
   end
 
   def test_sub_hash
@@ -1068,6 +1074,7 @@
     assert_equal([], "".split(//, 1))
     assert_equal(["\0"], "\0".split(//))
     assert_equal(["*.c", "lib", "ext"], "\n\n\n\n\n\n*.c\n\n\n\nlib\n\n\n\n\next\n".split)
+    assert_equal("[2, 3]", [1,2,3].slice!(1,10000).inspect, "moved from btest/knownbug")
   end
 
   def test_squeeze
@@ -1506,6 +1513,73 @@
     assert_equal(676, count)
   end
 
+  def test_mod_check
+    assert_raise(RuntimeError) {
+      s = ""
+      s.sub!(/\A/) { s.replace "z" * 2000; "zzz" }
+    }
+  end
+
+  def test_frozen_check
+    assert_raise(RuntimeError) {
+      s = ""
+      s.sub!(/\A/) { s.freeze; "zzz" }
+    }
+  end
+
+  def test_tainted_str_new
+    a = []
+    a << a
+    s = a.inspect
+    assert(s.tainted?)
+    assert_equal("[[...]]", s)
+  end
+
+  class S2 < String
+  end
+  def test_str_new4
+    s = (0..54).to_a.join # length = 100
+    s2 = S2.new(s[10,90])
+    s3 = s2[10,80]
+    assert_equal((10..54).to_a.to_a.join, s2)
+    assert_equal((15..54).to_a.to_a.join, s3)
+  end
+
+  def test_rb_str_new4
+    s = "a" * 100
+    s2 = s[10,90]
+    assert_equal("a" * 90, s2)
+    s3 = s2[10,80]
+    assert_equal("a" * 80, s3)
+  end
+
+  class StringLike
+    def initialize(str)
+      @str = str
+    end
+
+    def to_str
+      @str
+    end
+  end
+
+  def test_rb_str_to_str
+    #assert_equal("ab", "a" + StringLike.new("b"))
+  end
+
+  def test_rb_str_shared_replace
+    s = "a" * 100
+    s.succ!
+    assert_equal("a" * 99 + "b", s)
+    s = ""
+    s.succ!
+    assert_equal("", s)
+  end
+
+  def test_times
+    assert_raise(ArgumentError) { "a" * (-1) }
+  end
+
   def test_splice!
     l = S("1234\n234\n34\n4\n")
     assert_equal(S("1234\n"), l.slice!(/\A.*\n/), "[ruby-dev:31665]")
@@ -1519,7 +1593,7 @@
     assert("abc".end_with?("c"))
   end
 
-  def test_times
+  def test_times2
     s1 = ''
     100.times {|n|
       s2 = "a" * n
@@ -1605,4 +1679,8 @@
     end
     assert_equal(:foo, c.new.foo)
   end
+
+  def test_gsub_enumerator
+    assert_normal_exit %q{"abc".gsub(/./).next}, "[ruby-dev:34828]"
+  end
 end

Modified: MacRuby/branches/testing/test/ruby/test_struct.rb
===================================================================
--- MacRuby/branches/testing/test/ruby/test_struct.rb	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/test/ruby/test_struct.rb	2008-06-05 08:33:02 UTC (rev 249)
@@ -206,4 +206,10 @@
     o = klass.new(1)
     assert_equal(1, o.size)
   end
+
+  def test_error
+    assert_raise(TypeError){
+      Struct.new(0)
+    }
+  end
 end

Modified: MacRuby/branches/testing/test/ruby/test_thread.rb
===================================================================
--- MacRuby/branches/testing/test/ruby/test_thread.rb	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/test/ruby/test_thread.rb	2008-06-05 08:33:02 UTC (rev 249)
@@ -499,4 +499,10 @@
     }.join
     t.join
   end
+
+  def test_uninitialized
+    c = Class.new(Thread)
+    c.class_eval { def initialize; end }
+    assert_raise(ThreadError) { c.new.start }
+  end
 end

Modified: MacRuby/branches/testing/test/ruby/test_utf16.rb
===================================================================
--- MacRuby/branches/testing/test/ruby/test_utf16.rb	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/test/ruby/test_utf16.rb	2008-06-05 08:33:02 UTC (rev 249)
@@ -290,4 +290,69 @@
     assert_equal(e, "abc".encode("utf-16be").count("^b".encode("utf-16be")))
     assert_equal(e, "abc".encode("utf-16le").count("^b".encode("utf-16le")))
   end
+
+  def test_header
+    assert_raise(ArgumentError) { eval("# encoding:utf-16le\nfoo") }
+    assert_raise(ArgumentError) { eval("# encoding:utf-16be\nfoo") }
+  end
+
+
+  def test_is_mbc_newline
+    sl = "f\0o\0o\0\n\0b\0a\0r\0\n\0b\0a\0z\0\n\0".force_encoding("utf-16le")
+    sb = "\0f\0o\0o\0\n\0b\0a\0r\0\n\0b\0a\0z\0\n".force_encoding("utf-16be")
+    al = sl.lines.to_a
+    ab = sb.lines.to_a
+    assert_equal("f\0o\0o\0\n\0".force_encoding("utf-16le"), al.shift)
+    assert_equal("b\0a\0r\0\n\0".force_encoding("utf-16le"), al.shift)
+    assert_equal("b\0a\0z\0\n\0".force_encoding("utf-16le"), al.shift)
+    assert_equal("\0f\0o\0o\0\n".force_encoding("utf-16be"), ab.shift)
+    assert_equal("\0b\0a\0r\0\n".force_encoding("utf-16be"), ab.shift)
+    assert_equal("\0b\0a\0z\0\n".force_encoding("utf-16be"), ab.shift)
+
+    sl = "f\0o\0o\0\n\0".force_encoding("utf-16le")
+    sb = "\0f\0o\0o\0\n".force_encoding("utf-16be")
+    sl2 = "f\0o\0o\0".force_encoding("utf-16le")
+    sb2 = "\0f\0o\0o".force_encoding("utf-16be")
+    assert_equal(sl2, sl.chomp)
+    assert_equal(sl2, sl.chomp.chomp)
+    assert_equal(sb2, sb.chomp)
+    assert_equal(sb2, sb.chomp.chomp)
+
+    sl = "f\0o\0o\0\n".force_encoding("utf-16le")
+    sb = "\0f\0o\0o\n".force_encoding("utf-16be")
+    assert_equal(sl, sl.chomp)
+    assert_equal(sb, sb.chomp)
+  end
+
+  def test_code_to_mbc
+    assert_equal("a\0".force_encoding("utf-16le"), "a".ord.chr("utf-16le"))
+    assert_equal("\0a".force_encoding("utf-16be"), "a".ord.chr("utf-16be"))
+  end
+
+  def utf8_to_utf16(s, e)
+    s.chars.map {|c| c.ord.chr(e) }.join
+  end
+
+  def test_mbc_case_fold
+    rl = Regexp.new(utf8_to_utf16("^(\u3042)(a)\\1\\2$", "utf-16le"), "i")
+    rb = Regexp.new(utf8_to_utf16("^(\u3042)(a)\\1\\2$", "utf-16be"), "i")
+    assert_equal(Encoding.find("utf-16le"), rl.encoding)
+    assert_equal(Encoding.find("utf-16be"), rb.encoding)
+    assert_match(rl, utf8_to_utf16("\u3042a\u3042a", "utf-16le"))
+    assert_match(rb, utf8_to_utf16("\u3042a\u3042a", "utf-16be"))
+  end
+
+  def test_surrogate_pair
+    sl = "\x42\xd8\xb7\xdf".force_encoding("utf-16le")
+    sb = "\xd8\x42\xdf\xb7".force_encoding("utf-16be")
+
+    assert_equal(1, sl.size)
+    assert_equal(1, sb.size)
+    assert_equal(0x20bb7, sl.ord)
+    assert_equal(0x20bb7, sb.ord)
+    assert_equal(sl, 0x20bb7.chr("utf-16le"))
+    assert_equal(sb, 0x20bb7.chr("utf-16be"))
+    assert_equal("", sl.chop)
+    assert_equal("", sb.chop)
+  end
 end

Modified: MacRuby/branches/testing/test/ruby/test_utf32.rb
===================================================================
--- MacRuby/branches/testing/test/ruby/test_utf32.rb	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/test/ruby/test_utf32.rb	2008-06-05 08:33:02 UTC (rev 249)
@@ -20,8 +20,74 @@
 
   def test_substr
     assert_str_equal(
+      "abcdefgh".force_encoding("utf-32le"),
+      "abcdefgh".force_encoding("utf-32le")[0,3])
+    assert_str_equal(
       "abcdefgh".force_encoding("utf-32be"),
       "abcdefgh".force_encoding("utf-32be")[0,3])
   end
+
+  def test_mbc_len
+    al = "abcdefghijkl".force_encoding("utf-32le").each_char.to_a
+    ab = "abcdefghijkl".force_encoding("utf-32be").each_char.to_a
+    assert_equal("abcd".force_encoding("utf-32le"), al.shift)
+    assert_equal("efgh".force_encoding("utf-32le"), al.shift)
+    assert_equal("ijkl".force_encoding("utf-32le"), al.shift)
+    assert_equal("abcd".force_encoding("utf-32be"), ab.shift)
+    assert_equal("efgh".force_encoding("utf-32be"), ab.shift)
+    assert_equal("ijkl".force_encoding("utf-32be"), ab.shift)
+  end
+
+  def ascii_to_utf16le(s)
+    s.unpack("C*").map {|x| [x,0,0,0] }.flatten.pack("C*").force_encoding("utf-32le")
+  end
+
+  def ascii_to_utf16be(s)
+    s.unpack("C*").map {|x| [0,0,0,x] }.flatten.pack("C*").force_encoding("utf-32be")
+  end
+
+  def test_mbc_newline
+    al = ascii_to_utf16le("foo\nbar\nbaz\n").lines.to_a
+    ab = ascii_to_utf16be("foo\nbar\nbaz\n").lines.to_a
+
+    assert_equal(ascii_to_utf16le("foo\n"), al.shift)
+    assert_equal(ascii_to_utf16le("bar\n"), al.shift)
+    assert_equal(ascii_to_utf16le("baz\n"), al.shift)
+    assert_equal(ascii_to_utf16be("foo\n"), ab.shift)
+    assert_equal(ascii_to_utf16be("bar\n"), ab.shift)
+    assert_equal(ascii_to_utf16be("baz\n"), ab.shift)
+
+    sl = "a\0".force_encoding("utf-32le")
+    sb = "a\0".force_encoding("utf-32be")
+    assert_equal(sl, sl.chomp)
+    assert_equal(sb, sb.chomp)
+  end
+
+  def test_mbc_to_code
+    sl = "a\0\0\0".force_encoding("utf-32le")
+    sb = "\0\0\0a".force_encoding("utf-32be")
+    assert_equal("a".ord, sl.ord)
+    assert_equal("a".ord, sb.ord)
+  end
+
+  def utf8_to_utf32(s, e)
+    s.chars.map {|c| c.ord.chr(e) }.join
+  end
+
+  def test_mbc_case_fold
+    rl = Regexp.new(utf8_to_utf32("^(\u3042)(a)\\1\\2$", "utf-32le"), "i")
+    rb = Regexp.new(utf8_to_utf32("^(\u3042)(a)\\1\\2$", "utf-32be"), "i")
+    assert_equal(Encoding.find("utf-32le"), rl.encoding)
+    assert_equal(Encoding.find("utf-32be"), rb.encoding)
+    assert_match(rl, utf8_to_utf32("\u3042a\u3042a", "utf-32le"))
+    assert_match(rb, utf8_to_utf32("\u3042a\u3042a", "utf-32be"))
+  end
+
+  def test_code_to_mbc
+    sl = "a\0\0\0".force_encoding("utf-32le")
+    sb = "\0\0\0a".force_encoding("utf-32be")
+    assert_equal(sl, "a".ord.chr("utf-32le"))
+    assert_equal(sb, "a".ord.chr("utf-32be"))
+  end
 end
 

Copied: MacRuby/branches/testing/test/ruby/test_windows_1251.rb (from rev 248, MacRuby/trunk/test/ruby/test_windows_1251.rb)
===================================================================
--- MacRuby/branches/testing/test/ruby/test_windows_1251.rb	                        (rev 0)
+++ MacRuby/branches/testing/test/ruby/test_windows_1251.rb	2008-06-05 08:33:02 UTC (rev 249)
@@ -0,0 +1,16 @@
+# encoding:windows-1251
+
+require "test/unit"
+
+class TestWindows1251 < Test::Unit::TestCase
+  def test_windows_1251
+    (0xc0..0xdf).each do |c|
+      c1 = c.chr("windows-1251")
+      c2 = (c + 0x20).chr("windows-1251")
+      assert_match(/^(#{ c1 })\1$/i, c2 + c1)
+      assert_match(/^(#{ c2 })\1$/i, c1 + c2)
+      assert_match(/^[#{ c1 }]+$/i, c2 + c1)
+      assert_match(/^[#{ c2 }]+$/i, c1 + c2)
+    end
+  end
+end

Modified: MacRuby/branches/testing/test/test_delegate.rb
===================================================================
--- MacRuby/branches/testing/test/test_delegate.rb	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/test/test_delegate.rb	2008-06-05 08:33:02 UTC (rev 249)
@@ -12,4 +12,9 @@
     obj.extend M
     assert_equal(:m, obj.m, "[ruby-dev:33116]")
   end
+
+  def test_systemcallerror_eq
+    e = SystemCallError.new(0)
+    assert((SimpleDelegator.new(e) == e) == (e == SimpleDelegator.new(e)), "[ruby-dev:34808]")
+  end
 end

Copied: MacRuby/branches/testing/test/webrick/.htaccess (from rev 248, MacRuby/trunk/test/webrick/.htaccess)
===================================================================
--- MacRuby/branches/testing/test/webrick/.htaccess	                        (rev 0)
+++ MacRuby/branches/testing/test/webrick/.htaccess	2008-06-05 08:33:02 UTC (rev 249)
@@ -0,0 +1 @@
+this file should not be published.

Modified: MacRuby/branches/testing/test/webrick/test_cgi.rb
===================================================================
--- MacRuby/branches/testing/test/webrick/test_cgi.rb	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/test/webrick/test_cgi.rb	2008-06-05 08:33:02 UTC (rev 249)
@@ -1,20 +1,13 @@
 require "webrick"
 require File.join(File.dirname(__FILE__), "utils.rb")
 require "test/unit"
-begin
-  loadpath = $:.dup
-  $:.replace($: | [File.expand_path("../ruby", File.dirname(__FILE__))])
-  require 'envutil'
-ensure
-  $:.replace(loadpath)
-end
 
 class TestWEBrickCGI < Test::Unit::TestCase
   def test_cgi
     accepted = started = stopped = 0
     requested0 = requested1 = 0
     config = {
-      :CGIInterpreter => EnvUtil.rubybin,
+      :CGIInterpreter => TestWEBrick::RubyBin,
       :DocumentRoot => File.dirname(__FILE__),
       :DirectoryIndex => ["webrick.cgi"],
       :RequestHandler => Proc.new{|req, res|

Modified: MacRuby/branches/testing/test/webrick/test_filehandler.rb
===================================================================
--- MacRuby/branches/testing/test/webrick/test_filehandler.rb	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/test/webrick/test_filehandler.rb	2008-06-05 08:33:02 UTC (rev 249)
@@ -9,6 +9,10 @@
     klass.new(WEBrick::Config::HTTP, filename)
   end
 
+  def windows?
+    File.directory?("\\")
+  end
+
   def get_res_body(res)
     if defined? res.body.read
       res.body.read
@@ -119,10 +123,82 @@
       http = Net::HTTP.new(addr, port)
       req = Net::HTTP::Get.new("/../../")
       http.request(req){|res| assert_equal("400", res.code) }
-      req = Net::HTTP::Get.new(
-        "/..%5c..%5c..%5c..%5c..%5c..%5c..%5c..%5c..%5c..%5c..%5c..%5cboot.ini"
-      )
+      req = Net::HTTP::Get.new("/..%5c../#{File.basename(__FILE__)}")
+      http.request(req){|res| assert_equal(windows? ? "200" : "404", res.code) }
+      req = Net::HTTP::Get.new("/..%5c..%5cruby.c")
       http.request(req){|res| assert_equal("404", res.code) }
     end
   end
+
+  def test_unwise_in_path
+    if windows?
+      config = { :DocumentRoot => File.dirname(__FILE__), }
+      this_file = File.basename(__FILE__)
+      TestWEBrick.start_httpserver(config) do |server, addr, port|
+        http = Net::HTTP.new(addr, port)
+        req = Net::HTTP::Get.new("/..%5c..")
+        http.request(req){|res| assert_equal("301", res.code) }
+      end
+    end
+  end
+
+  def test_short_filename
+    config = {
+      :CGIInterpreter => TestWEBrick::RubyBin,
+      :DocumentRoot => File.dirname(__FILE__),
+      :CGIPathEnv => ENV['PATH'],
+    }
+    TestWEBrick.start_httpserver(config) do |server, addr, port|
+      http = Net::HTTP.new(addr, port)
+
+      req = Net::HTTP::Get.new("/webric~1.cgi/test")
+      http.request(req) do |res|
+        if windows?
+          assert_equal("200", res.code)
+          assert_equal("/test", res.body)
+        else
+          assert_equal("404", res.code)
+        end
+      end
+
+      req = Net::HTTP::Get.new("/.htaccess")
+      http.request(req) {|res| assert_equal("404", res.code) }
+      req = Net::HTTP::Get.new("/htacce~1")
+      http.request(req) {|res| assert_equal("404", res.code) }
+      req = Net::HTTP::Get.new("/HTACCE~1")
+      http.request(req) {|res| assert_equal("404", res.code) }
+    end
+  end
+
+  def test_script_disclosure
+    config = {
+      :CGIInterpreter => TestWEBrick::RubyBin,
+      :DocumentRoot => File.dirname(__FILE__),
+      :CGIPathEnv => ENV['PATH'],
+    }
+    TestWEBrick.start_httpserver(config) do |server, addr, port|
+      http = Net::HTTP.new(addr, port)
+
+      req = Net::HTTP::Get.new("/webrick.cgi/test")
+      http.request(req) do |res|
+        assert_equal("200", res.code)
+        assert_equal("/test", res.body)
+      end
+
+      response_assertion = Proc.new do |res|
+        if windows?
+          assert_equal("200", res.code)
+          assert_equal("/test", res.body)
+        else
+          assert_equal("404", res.code)
+        end
+      end
+      req = Net::HTTP::Get.new("/webrick.cgi%20/test")
+      http.request(req, &response_assertion)
+      req = Net::HTTP::Get.new("/webrick.cgi./test")
+      http.request(req, &response_assertion)
+      req = Net::HTTP::Get.new("/webrick.cgi::$DATA/test")
+      http.request(req, &response_assertion)
+    end
+  end
 end

Modified: MacRuby/branches/testing/test/webrick/utils.rb
===================================================================
--- MacRuby/branches/testing/test/webrick/utils.rb	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/test/webrick/utils.rb	2008-06-05 08:33:02 UTC (rev 249)
@@ -1,3 +1,10 @@
+begin
+  loadpath = $:.dup
+  $:.replace($: | [File.expand_path("../ruby", File.dirname(__FILE__))])
+  require 'envutil'
+ensure
+  $:.replace(loadpath)
+end
 require "webrick"
 begin
   require "webrick/https"
@@ -12,6 +19,11 @@
     return self
   end
 
+  RubyBin = "\"#{EnvUtil.rubybin}\""
+  RubyBin << " \"-I#{File.expand_path("../..", File.dirname(__FILE__))}/lib\""
+  RubyBin << " \"-I#{File.dirname(EnvUtil.rubybin)}/.ext/common\""
+  RubyBin << " \"-I#{File.dirname(EnvUtil.rubybin)}/.ext/#{RUBY_PLATFORM}\""
+
   module_function
 
   def start_server(klass, config={}, &block)

Copied: MacRuby/branches/testing/test/webrick/webrick_long_filename.cgi (from rev 248, MacRuby/trunk/test/webrick/webrick_long_filename.cgi)
===================================================================
--- MacRuby/branches/testing/test/webrick/webrick_long_filename.cgi	                        (rev 0)
+++ MacRuby/branches/testing/test/webrick/webrick_long_filename.cgi	2008-06-05 08:33:02 UTC (rev 249)
@@ -0,0 +1,36 @@
+#!ruby -d
+require "webrick/cgi"
+
+class TestApp < WEBrick::CGI
+  def do_GET(req, res)
+    res["content-type"] = "text/plain"
+    if (p = req.path_info) && p.length > 0
+      res.body = p
+    elsif (q = req.query).size > 0
+      res.body = q.keys.sort.collect{|key|
+        q[key].list.sort.collect{|v|
+          "#{key}=#{v}"
+        }.join(", ")
+      }.join(", ")
+    elsif %r{/$} =~ req.request_uri.to_s
+      res.body = ""
+      res.body << req.request_uri.to_s  << "\n"
+      res.body << req.script_name
+    elsif !req.cookies.empty?
+      res.body = req.cookies.inject(""){|result, cookie|
+        result << "%s=%s\n" % [cookie.name, cookie.value]
+      }
+      res.cookies << WEBrick::Cookie.new("Customer", "WILE_E_COYOTE")
+      res.cookies << WEBrick::Cookie.new("Shipping", "FedEx")
+    else
+      res.body = req.script_name
+    end
+  end
+
+  def do_POST(req, res)
+    do_GET(req, res)
+  end
+end
+
+cgi = TestApp.new
+cgi.start

Modified: MacRuby/branches/testing/thread.c
===================================================================
--- MacRuby/branches/testing/thread.c	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/thread.c	2008-06-05 08:33:02 UTC (rev 249)
@@ -2,7 +2,7 @@
 
   thread.c -
 
-  $Author: akr $
+  $Author: nobu $
 
   Copyright (C) 2004-2007 Koichi Sasada
 
@@ -79,8 +79,9 @@
 
 #define THREAD_SYSTEM_DEPENDENT_IMPLEMENTATION
 
-static void set_unblock_function(rb_thread_t *th, rb_unblock_function_t *func, void *ptr,
-				 rb_unblock_function_t **oldfunc, void **oldptr);
+static void set_unblock_function(rb_thread_t *th, rb_unblock_function_t *func, void *arg,
+				 struct rb_unblock_callback *old);
+static void reset_unblock_function(rb_thread_t *th, const struct rb_unblock_callback *old);
 
 #define GVL_UNLOCK_BEGIN() do { \
   rb_thread_t *_th_stored = GET_THREAD(); \
@@ -95,9 +96,8 @@
 #define BLOCKING_REGION(exec, ubf, ubfarg) do { \
     rb_thread_t *__th = GET_THREAD(); \
     int __prev_status = __th->status; \
-    rb_unblock_function_t *__oldubf; \
-    void *__oldubfarg; \
-    set_unblock_function(__th, ubf, ubfarg, &__oldubf, &__oldubfarg); \
+    struct rb_unblock_callback __oldubf; \
+    set_unblock_function(__th, ubf, ubfarg, &__oldubf); \
     __th->status = THREAD_STOPPED; \
     thread_debug("enter blocking region (%p)\n", __th); \
     GVL_UNLOCK_BEGIN(); {\
@@ -106,7 +106,7 @@
     GVL_UNLOCK_END(); \
     thread_debug("leave blocking region (%p)\n", __th); \
     remove_signal_thread_list(__th); \
-    set_unblock_function(__th, __oldubf, __oldubfarg, 0, 0); \
+    reset_unblock_function(__th, &__oldubf); \
     if (__th->status == THREAD_STOPPED) { \
 	__th->status = __prev_status; \
     } \
@@ -195,7 +195,7 @@
 
 static void
 set_unblock_function(rb_thread_t *th, rb_unblock_function_t *func, void *arg,
-		     rb_unblock_function_t **oldfunc, void **oldarg)
+		     struct rb_unblock_callback *old)
 {
   check_ints:
     RUBY_VM_CHECK_INTS(); /* check signal or so */
@@ -205,21 +205,28 @@
 	goto check_ints;
     }
     else {
-	if (oldfunc) *oldfunc = th->unblock_function;
-	if (oldarg) *oldarg = th->unblock_function_arg;
-	th->unblock_function = func;
-	th->unblock_function_arg = arg;
+	if (old) *old = th->unblock;
+	th->unblock.func = func;
+	th->unblock.arg = arg;
     }
     native_mutex_unlock(&th->interrupt_lock);
 }
 
 static void
+reset_unblock_function(rb_thread_t *th, const struct rb_unblock_callback *old)
+{
+    native_mutex_lock(&th->interrupt_lock);
+    th->unblock = *old;
+    native_mutex_unlock(&th->interrupt_lock);
+}
+
+static void
 rb_thread_interrupt(rb_thread_t *th)
 {
     native_mutex_lock(&th->interrupt_lock);
     RUBY_VM_SET_INTERRUPT(th);
-    if (th->unblock_function) {
-	(th->unblock_function)(th->unblock_function_arg);
+    if (th->unblock.func) {
+	(th->unblock.func)(th->unblock.arg);
     }
     else {
 	/* none */
@@ -816,6 +823,7 @@
 void
 rb_thread_execute_interrupts(rb_thread_t *th)
 {
+    if (th->raised_flag) return;
     while (th->interrupt_flag) {
 	int status = th->status;
 	th->status = THREAD_RUNNABLE;
@@ -1465,7 +1473,7 @@
 static VALUE
 rb_thread_inspect(VALUE thread)
 {
-    char *cname = rb_obj_classname(thread);
+    const char *cname = rb_obj_classname(thread);
     rb_thread_t *th;
     const char *status;
     VALUE str;
@@ -2487,7 +2495,7 @@
 rb_mutex_unlock(VALUE self)
 {
     mutex_t *mutex;
-    char *err = NULL;
+    const char *err = NULL;
     GetMutexPtr(self, mutex);
 
     native_mutex_lock(&mutex->lock);
@@ -3035,7 +3043,7 @@
     return trace;
 }
 
-static char *
+static const char *
 get_event_name(rb_event_flag_t event)
 {
     switch (event) {
@@ -3252,6 +3260,9 @@
     }
 
     rb_thread_create_timer_thread();
+
+    (void)native_mutex_trylock;
+    (void)ruby_thread_set_native;
 }
 
 int

Modified: MacRuby/branches/testing/thread_pthread.c
===================================================================
--- MacRuby/branches/testing/thread_pthread.c	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/thread_pthread.c	2008-06-05 08:33:02 UTC (rev 249)
@@ -149,6 +149,7 @@
 
     pthread_key_create(&ruby_native_thread_key, NULL);
     th->thread_id = pthread_self();
+    native_cond_initialize(&th->native_thread_data.sleep_cond);
     ruby_thread_set_native(th);
     native_mutex_initialize(&signal_thread_list_lock);
     posix_signal(SIGVTALRM, null_func);
@@ -363,12 +364,12 @@
     max = sched_get_priority_max(policy);
     min = sched_get_priority_min(policy);
 
-    if (min < priority) {
+    if (min > priority) {
+	priority = min;
+    }
+    else if (max < priority) {
 	priority = max;
     }
-    else if (max > priority) {
-	priority = min;
-    }
 
     sp.sched_priority = priority;
     pthread_setschedparam(th->thread_id, policy, &sp);
@@ -429,8 +430,8 @@
     GVL_UNLOCK_BEGIN();
     {
 	pthread_mutex_lock(&th->interrupt_lock);
-	th->unblock_function = ubf_pthread_cond_signal;
-	th->unblock_function_arg = th;
+	th->unblock.func = ubf_pthread_cond_signal;
+	th->unblock.arg = th;
 
 	if (RUBY_VM_INTERRUPTED(th)) {
 	    /* interrupted.  return immediate */
@@ -438,9 +439,11 @@
 	}
 	else {
 	    if (tv == 0 || ts.tv_sec < tvn.tv_sec /* overflow */ ) {
+		int r;
 		thread_debug("native_sleep: pthread_cond_wait start\n");
-		pthread_cond_wait(&th->native_thread_data.sleep_cond,
+		r = pthread_cond_wait(&th->native_thread_data.sleep_cond,
 				  &th->interrupt_lock);
+                if (r) rb_bug("pthread_cond_wait: %d", r);
 		thread_debug("native_sleep: pthread_cond_wait end\n");
 	    }
 	    else {
@@ -449,11 +452,13 @@
 			     (unsigned long)ts.tv_sec, ts.tv_nsec);
 		r = pthread_cond_timedwait(&th->native_thread_data.sleep_cond,
 					   &th->interrupt_lock, &ts);
+		if (r && r != ETIMEDOUT) rb_bug("pthread_cond_timedwait: %d", r);
+
 		thread_debug("native_sleep: pthread_cond_timedwait end (%d)\n", r);
 	    }
 	}
-	th->unblock_function = 0;
-	th->unblock_function_arg = 0;
+	th->unblock.func = 0;
+	th->unblock.arg = 0;
 
 	pthread_mutex_unlock(&th->interrupt_lock);
 	th->status = prev_status;

Modified: MacRuby/branches/testing/thread_win32.c
===================================================================
--- MacRuby/branches/testing/thread_win32.c	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/thread_win32.c	2008-06-05 08:33:02 UTC (rev 249)
@@ -220,8 +220,8 @@
 	int status = th->status;
 
 	th->status = THREAD_STOPPED;
-	th->unblock_function = ubf_handle;
-	th->unblock_function_arg = th;
+	th->unblock.func = ubf_handle;
+	th->unblock.arg = th;
 
 	if (RUBY_VM_INTERRUPTED(th)) {
 	    /* interrupted.  return immediate */
@@ -232,8 +232,8 @@
 	    thread_debug("native_sleep done (%lu)\n", ret);
 	}
 
-	th->unblock_function = 0;
-	th->unblock_function_arg = 0;
+	th->unblock.func = 0;
+	th->unblock.arg = 0;
 	th->status = status;
     }
     GVL_UNLOCK_END();

Modified: MacRuby/branches/testing/time.c
===================================================================
--- MacRuby/branches/testing/time.c	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/time.c	2008-06-05 08:33:02 UTC (rev 249)
@@ -2,7 +2,7 @@
 
   time.c -
 
-  $Author: akr $
+  $Author: nobu $
   created at: Tue Dec 28 14:31:59 JST 1993
 
   Copyright (C) 1993-2007 Yukihiro Matsumoto
@@ -333,7 +333,7 @@
     return t;
 }
 
-static const char *const months[] = {
+static const char months[][4] = {
     "jan", "feb", "mar", "apr", "may", "jun",
     "jul", "aug", "sep", "oct", "nov", "dec",
 };
@@ -829,7 +829,10 @@
 make_time_t(struct tm *tptr, int utc_p)
 {
     time_t t;
-    struct tm *tmp, buf;
+#ifdef NEGATIVE_TIME_T
+    struct tm *tmp;
+#endif
+    struct tm buf;
     buf = *tptr;
     if (utc_p) {
 #if defined(HAVE_TIMEGM)

Modified: MacRuby/branches/testing/tool/instruction.rb
===================================================================
--- MacRuby/branches/testing/tool/instruction.rb	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/tool/instruction.rb	2008-06-05 08:33:02 UTC (rev 249)
@@ -66,13 +66,14 @@
         ret = "int inc = 0;\n"
 
         @opes.each_with_index{|(t, v), i|
-          if t == 'rb_num_t'
-            ret << "        unsigned long #{v} = FIX2INT(opes[#{i}]);\n"
+          if t == 'rb_num_t' && ((re = /\b#{v}\b/n) =~ @sp_inc ||
+                                 @defopes.any?{|t, val| re =~ val})
+            ret << "        #{t} #{v} = FIX2INT(opes[#{i}]);\n"
           end
         }
         @defopes.each_with_index{|((t, var), val), i|
-          if t == 'rb_num_t' && val != '*'
-            ret << "        unsigned long #{var} = #{val};\n"
+          if t == 'rb_num_t' && val != '*' && /\b#{var}\b/ =~ @sp_inc
+            ret << "        #{t} #{var} = #{val};\n"
           end
         }
 
@@ -707,7 +708,10 @@
           break
         end
 
-        ops << "  #{type} #{var} = (#{type})GET_OPERAND(#{i+1});"
+        re = /\b#{var}\b/n
+        if re =~ insn.body or re =~ insn.sp_inc or insn.rets.any?{|t, v| re =~ v}
+          ops << "  #{type} #{var} = (#{type})GET_OPERAND(#{i+1});"
+        end
         n   += 1
       }
       @opn = n

Modified: MacRuby/branches/testing/transcode.c
===================================================================
--- MacRuby/branches/testing/transcode.c	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/transcode.c	2008-06-05 08:33:02 UTC (rev 249)
@@ -2,7 +2,7 @@
 
   transcode.c -
 
-  $Author: nobu $
+  $Author: naruse $
   created at: Tue Oct 30 16:10:22 JST 2007
 
   Copyright (C) 2007 Martin Duerst
@@ -329,7 +329,7 @@
 	    my_transcoding.ruby_string_dest = dest;
 	    (*my_transcoder->preprocessor)(&fromp, &bp, (sp+slen), (bp+blen), &my_transcoding);
 	    if (fromp != sp+slen) {
-		rb_raise(rb_eArgError, "not fully converted, %d bytes left", sp+slen-fromp);
+		rb_raise(rb_eArgError, "not fully converted, %td bytes left", sp+slen-fromp);
 	    }
 	    buf = (unsigned char *)RSTRING_PTR(dest);
 	    *bp = '\0';
@@ -346,7 +346,7 @@
 
 	transcode_loop(&fromp, &bp, (sp+slen), (bp+blen), my_transcoder, &my_transcoding, options);
 	if (fromp != sp+slen) {
-	    rb_raise(rb_eArgError, "not fully converted, %d bytes left", sp+slen-fromp);
+	    rb_raise(rb_eArgError, "not fully converted, %td bytes left", sp+slen-fromp);
 	}
 	buf = (unsigned char *)RSTRING_PTR(dest);
 	*bp = '\0';
@@ -361,7 +361,7 @@
 	    my_transcoding.ruby_string_dest = dest;
 	    (*my_transcoder->postprocessor)(&fromp, &bp, (sp+slen), (bp+blen), &my_transcoding);
 	    if (fromp != sp+slen) {
-		rb_raise(rb_eArgError, "not fully converted, %d bytes left", sp+slen-fromp);
+		rb_raise(rb_eArgError, "not fully converted, %td bytes left", sp+slen-fromp);
 	    }
 	    buf = (unsigned char *)RSTRING_PTR(dest);
 	    *bp = '\0';
@@ -400,7 +400,7 @@
  */
 
 static VALUE
-rb_str_transcode_bang(int argc, VALUE *argv, VALUE str)
+str_encode_bang(int argc, VALUE *argv, VALUE str)
 {
     VALUE newstr = str;
     int encidx = str_transcode(argc, argv, &newstr);
@@ -434,30 +434,29 @@
  *  to be added.
  */
 
-static VALUE
-rb_str_transcode(int argc, VALUE *argv, VALUE str)
-{
-    str = rb_str_dup(str);
-    return rb_str_transcode_bang(argc, argv, str);
-}
-
 #else // WITH_OBJC
 
 static VALUE
-rb_str_transcode(int argc, VALUE *argv, VALUE self)
+str_encode_bang(int argc, VALUE *argv, VALUE self)
 {
     /* TODO */
     return self;
 }
 
+#endif
+
 static VALUE
-rb_str_transcode_bang(int argc, VALUE *argv, VALUE self)
+str_encode(int argc, VALUE *argv, VALUE str)
 {
-    /* TODO */
-    return self;
+    str = rb_str_dup(str);
+    return str_encode_bang(argc, argv, str);
 }
 
-#endif
+VALUE
+rb_str_transcode(VALUE str, VALUE to)
+{
+    return str_encode(1, &to, str);
+}
 
 void
 Init_transcode(void)
@@ -470,6 +469,6 @@
     sym_ignore = ID2SYM(rb_intern("ignore"));
 #endif
 
-    rb_define_method(rb_cString, "encode", rb_str_transcode, -1);
-    rb_define_method(rb_cString, "encode!", rb_str_transcode_bang, -1);
+    rb_define_method(rb_cString, "encode", str_encode, -1);
+    rb_define_method(rb_cString, "encode!", str_encode_bang, -1);
 }

Modified: MacRuby/branches/testing/util.c
===================================================================
--- MacRuby/branches/testing/util.c	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/util.c	2008-06-05 08:33:02 UTC (rev 249)
@@ -5,7 +5,7 @@
   $Author: nobu $
   created at: Fri Mar 10 17:22:34 JST 1995
 
-  Copyright (C) 1993-2007 Yukihiro Matsumoto
+  Copyright (C) 1993-2008 Yukihiro Matsumoto
 
 **********************************************************************/
 
@@ -48,7 +48,7 @@
 unsigned long
 ruby_scan_hex(const char *start, int len, int *retlen)
 {
-    static char hexdigit[] = "0123456789abcdef0123456789ABCDEF";
+    static const char hexdigit[] = "0123456789abcdef0123456789ABCDEF";
     register const char *s = start;
     register unsigned long retval = 0;
     char *tmp;
@@ -999,8 +999,6 @@
 #define IEEE_Arith
 #endif
 
-#include "errno.h"
-
 #ifdef Bad_float_h
 
 #ifdef IEEE_Arith
@@ -2205,6 +2203,7 @@
     const char *s2;
 #endif
 
+    errno = 0;
     sign = nz0 = nz = 0;
     dval(rv) = 0.;
     for (s = s00;;s++)
@@ -2384,7 +2383,7 @@
 #endif
         dval(rv) = tens[k - 9] * dval(rv) + z;
     }
-    bd0 = 0;
+    bd0 = bb = bd = bs = delta = 0;
     if (nd <= DBL_DIG
 #ifndef RND_PRODQUOT
 #ifndef Honor_FLT_ROUNDS
@@ -3202,7 +3201,7 @@
 }
 
 static char *
-nrv_alloc(char *s, char **rve, int n)
+nrv_alloc(const char *s, char **rve, int n)
 {
     char *rv, *t;
 
@@ -3310,7 +3309,7 @@
     int denorm;
     ULong x;
 #endif
-    Bigint *b, *b1, *delta, *mlo, *mhi, *S;
+    Bigint *b, *b1, *delta, *mlo = 0, *mhi = 0, *S;
     double d2, ds, eps;
     char *s, *s0;
 #ifdef Honor_FLT_ROUNDS
@@ -3663,7 +3662,6 @@
 
     m2 = b2;
     m5 = b5;
-    mhi = mlo = 0;
     if (leftright) {
         i =
 #ifndef Sudden_Underflow

Modified: MacRuby/branches/testing/variable.c
===================================================================
--- MacRuby/branches/testing/variable.c	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/variable.c	2008-06-05 08:33:02 UTC (rev 249)
@@ -2,7 +2,7 @@
 
   variable.c -
 
-  $Author: akr $
+  $Author: nobu $
   created at: Tue Apr 19 23:55:15 JST 1994
 
   Copyright (C) 1993-2007 Yukihiro Matsumoto
@@ -284,13 +284,13 @@
     return rb_class_path(rb_class_real(klass));
 }
 
-char *
+const char *
 rb_class2name(VALUE klass)
 {
-    return (char *)RSTRING_CPTR(rb_class_name(klass));
+    return RSTRING_CPTR(rb_class_name(klass));
 }
 
-char *
+const char *
 rb_obj_classname(VALUE obj)
 {
     return rb_class2name(CLASS_OF(obj));
@@ -1030,7 +1030,6 @@
 #if WITH_OBJC
     CFMutableDictionaryRef obj_dict;
     CFMutableDictionaryRef clone_dict;
-    VALUE val;
 
     if (generic_iv_dict == NULL)
 	return;
@@ -1145,7 +1144,7 @@
     if (OBJ_FROZEN(obj)) rb_error_frozen("object");
 #if WITH_OBJC
     if (!rb_special_const_p(obj) && rb_objc_is_non_native(obj)) {
-	rb_objc_flag_set(obj, FL_EXIVAR, true);
+	rb_objc_flag_set((const void *)obj, FL_EXIVAR, true);
 	generic_ivar_set(obj, id, val);
 	return val;
     }

Modified: MacRuby/branches/testing/version.h
===================================================================
--- MacRuby/branches/testing/version.h	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/version.h	2008-06-05 08:33:02 UTC (rev 249)
@@ -1,15 +1,15 @@
 #define RUBY_VERSION "1.9.0"
-#define RUBY_RELEASE_DATE "2008-05-17"
+#define RUBY_RELEASE_DATE "2008-06-03"
 #define RUBY_VERSION_CODE 190
-#define RUBY_RELEASE_CODE 20080517
+#define RUBY_RELEASE_CODE 20080603
 #define RUBY_PATCHLEVEL 0
 
 #define RUBY_VERSION_MAJOR 1
 #define RUBY_VERSION_MINOR 9
 #define RUBY_VERSION_TEENY 0
 #define RUBY_RELEASE_YEAR 2008
-#define RUBY_RELEASE_MONTH 5
-#define RUBY_RELEASE_DAY 17
+#define RUBY_RELEASE_MONTH 6
+#define RUBY_RELEASE_DAY 3
 
 #ifdef RUBY_EXTERN
 RUBY_EXTERN const int ruby_version_code;

Modified: MacRuby/branches/testing/vm.c
===================================================================
--- MacRuby/branches/testing/vm.c	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/vm.c	2008-06-05 08:33:02 UTC (rev 249)
@@ -2,7 +2,7 @@
 
   vm.c -
 
-  $Author: mame $
+  $Author: nobu $
 
   Copyright (C) 2004-2007 Koichi Sasada
 
@@ -16,6 +16,7 @@
 
 #include "insnhelper.h"
 #include "vm_insnhelper.c"
+#include "vm_eval.c"
 
 #define BUFSIZE 0x100
 #define PROCDEBUG 0
@@ -32,8 +33,6 @@
 void vm_analysis_register(int reg, int isset);
 void vm_analysis_insn(int insn);
 
-static NODE *lfp_set_special_cref(VALUE *lfp, NODE * cref);
-
 #if OPT_STACK_CACHING
 static VALUE finish_insn_seq[1] = { BIN(finish_SC_ax_ax) };
 #elif OPT_CALL_THREADED_CODE
@@ -51,7 +50,7 @@
 /* control stack frame */
 
 static inline VALUE
-rb_vm_set_finish_env(rb_thread_t *th)
+rb_vm_set_finish_env(rb_thread_t * th)
 {
     vm_push_frame(th, 0, FRAME_MAGIC_FINISH,
 		  Qnil, th->cfp->lfp[0], 0,
@@ -60,8 +59,8 @@
     return Qtrue;
 }
 
-void
-rb_vm_set_top_stack(rb_thread_t *th, VALUE iseqval)
+static void
+vm_set_top_stack(rb_thread_t * th, VALUE iseqval)
 {
     rb_iseq_t *iseq;
     GetISeqPtr(iseqval, iseq);
@@ -78,11 +77,11 @@
 		  th->cfp->sp, 0, iseq->local_size);
 }
 
-void
-rb_vm_set_eval_stack(rb_thread_t *th, VALUE iseqval)
+static void
+vm_set_eval_stack(rb_thread_t * th, VALUE iseqval, const NODE *cref)
 {
     rb_iseq_t *iseq;
-    rb_block_t *block = th->base_block;
+    rb_block_t * const block = th->base_block;
     GetISeqPtr(iseqval, iseq);
 
     /* for return */
@@ -90,17 +89,32 @@
     vm_push_frame(th, iseq, FRAME_MAGIC_EVAL, block->self,
 		  GC_GUARDED_PTR(block->dfp), iseq->iseq_encoded,
 		  th->cfp->sp, block->lfp, iseq->local_size);
+
+    if (cref) {
+	th->cfp->dfp[-1] = (VALUE)cref;
+    }
 }
 
+rb_control_frame_t *
+vm_get_ruby_level_cfp(rb_thread_t *th, rb_control_frame_t *cfp)
+{
+    while (!RUBY_VM_CONTROL_FRAME_STACK_OVERFLOW_P(th, cfp)) {
+	if (RUBY_VM_NORMAL_ISEQ_P(cfp->iseq)) {
+	    return cfp;
+	}
+	cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
+    }
+    return 0;
+}
+
 /* Env */
 
 static void
-env_free(void *ptr)
+env_free(void * const ptr)
 {
-    rb_env_t *env;
     RUBY_FREE_ENTER("env");
     if (ptr) {
-	env = ptr;
+	const rb_env_t * const env = ptr;
 	RUBY_FREE_UNLESS_NULL(env->env);
 	ruby_xfree(ptr);
     }
@@ -108,12 +122,12 @@
 }
 
 static void
-env_mark(void *ptr)
+env_mark(void * const ptr)
 {
-    rb_env_t *env;
     RUBY_MARK_ENTER("env");
     if (ptr) {
-	env = ptr;
+	const rb_env_t * const env = ptr;
+
 	if (env->env) {
 	    /* TODO: should mark more restricted range */
 	    RUBY_GC_INFO("env->env\n");
@@ -152,7 +166,7 @@
 static VALUE check_env_value(VALUE envval);
 
 static int
-check_env(rb_env_t *env)
+check_env(rb_env_t * const env)
 {
     printf("---\n");
     printf("envptr: %p\n", &env->block.dfp[0]);
@@ -186,8 +200,8 @@
 }
 
 static VALUE
-vm_make_env_each(rb_thread_t *th, rb_control_frame_t *cfp,
-		 VALUE *envptr, VALUE *endptr)
+vm_make_env_each(rb_thread_t * const th, rb_control_frame_t * const cfp,
+		 VALUE *envptr, VALUE * const endptr)
 {
     VALUE envval, penvval = 0;
     rb_env_t *env;
@@ -263,12 +277,6 @@
     env->block.dfp = cfp->dfp;
     env->block.iseq = cfp->iseq;
 
-    if (VMDEBUG &&
-	(!(cfp->lfp[-1] == Qnil ||
-	  BUILTIN_TYPE(cfp->lfp[-1]) == T_VALUES))) {
-	rb_bug("invalid svar");
-    }
-
     if (!RUBY_VM_NORMAL_ISEQ_P(cfp->iseq)) {
 	/* TODO */
 	env->block.iseq = 0;
@@ -277,7 +285,7 @@
 }
 
 static int
-collect_local_variables_in_env(rb_env_t *env, VALUE ary)
+collect_local_variables_in_env(rb_env_t * const env, const VALUE ary)
 {
     int i;
     for (i = 0; i < env->block.iseq->local_table_size; i++) {
@@ -287,14 +295,16 @@
 	}
     }
     if (env->prev_envval) {
-	GetEnvPtr(env->prev_envval, env);
-	collect_local_variables_in_env(env, ary);
+	rb_env_t *prevenv;
+	GetEnvPtr(env->prev_envval, prevenv);
+	collect_local_variables_in_env(prevenv, ary);
     }
     return 0;
 }
 
 int
-vm_collect_local_variables_in_heap(rb_thread_t *th, VALUE *dfp, VALUE ary)
+vm_collect_local_variables_in_heap(rb_thread_t * const th,
+				   VALUE * const dfp, const VALUE ary)
 {
     if (ENV_IN_HEAP_P(th, dfp)) {
 	rb_env_t *env;
@@ -308,7 +318,7 @@
 }
 
 VALUE
-vm_make_env_object(rb_thread_t *th, rb_control_frame_t *cfp)
+vm_make_env_object(rb_thread_t * th, rb_control_frame_t *cfp)
 {
     VALUE envval;
 
@@ -327,7 +337,7 @@
 }
 
 void
-vm_stack_to_heap(rb_thread_t *th)
+vm_stack_to_heap(rb_thread_t * const th)
 {
     rb_control_frame_t *cfp = th->cfp;
     while ((cfp = vm_get_ruby_level_cfp(th, cfp)) != 0) {
@@ -358,7 +368,7 @@
 
 VALUE
 vm_make_proc(rb_thread_t *th,
-	     rb_control_frame_t *cfp, rb_block_t *block)
+	     rb_control_frame_t *cfp, const rb_block_t *block)
 {
     VALUE procval, envval, blockprocval = 0;
     rb_proc_t *proc;
@@ -389,7 +399,6 @@
     proc->block.proc = procval;
     proc->envval = envval;
     proc->safe_level = th->safe_level;
-    proc->special_cref_stack = lfp_get_special_cref(block->lfp);
 
     if (VMDEBUG) {
 	if (th->stack < block->dfp && block->dfp < th->stack + th->stack_size) {
@@ -403,153 +412,18 @@
     return procval;
 }
 
-/* C -> Ruby: method */
-
-VALUE
-vm_call0(rb_thread_t *th, VALUE klass, VALUE recv,
-	 VALUE id, ID oid, int argc, const VALUE *argv,
-	 NODE * body, int nosuper)
-{
-    VALUE val;
-    rb_block_t *blockptr = 0;
-
-    if (0) printf("id: %s, nd: %s, argc: %d, passed: %p\n",
-		  rb_id2name(id), ruby_node_name(nd_type(body)),
-		  argc, th->passed_block);
-
-    if (th->passed_block) {
-	blockptr = th->passed_block;
-	th->passed_block = 0;
-    }
-    switch (nd_type(body)) {
-      case RUBY_VM_METHOD_NODE:{
-	rb_control_frame_t *reg_cfp;
-	VALUE iseqval = (VALUE)body->nd_body;
-	int i;
-
-	rb_vm_set_finish_env(th);
-	reg_cfp = th->cfp;
-
-	CHECK_STACK_OVERFLOW(reg_cfp, argc + 1);
-
-	*reg_cfp->sp++ = recv;
-	for (i = 0; i < argc; i++) {
-	    *reg_cfp->sp++ = argv[i];
-	}
-
-	vm_setup_method(th, reg_cfp, argc, blockptr, 0, iseqval, recv, klass);
-	val = vm_eval_body(th);
-	break;
-      }
-      case NODE_CFUNC: {
-	EXEC_EVENT_HOOK(th, RUBY_EVENT_C_CALL, recv, id, klass);
-	{
-	    rb_control_frame_t *reg_cfp = th->cfp;
-	    rb_control_frame_t *cfp =
-		vm_push_frame(th, 0, FRAME_MAGIC_CFUNC,
-			      recv, (VALUE)blockptr, 0, reg_cfp->sp, 0, 1);
-
-	    cfp->method_id = id;
-	    cfp->method_class = klass;
-
-	    val = call_cfunc(body->nd_cfnc, recv, body->nd_argc, argc, argv);
-
-	    if (reg_cfp != th->cfp + 1) {
-		SDR2(reg_cfp);
-		SDR2(th->cfp-5);
-		rb_bug("cfp consistency error - call0");
-		th->cfp = reg_cfp;
-	    }
-	    vm_pop_frame(th);
-	}
-	EXEC_EVENT_HOOK(th, RUBY_EVENT_C_RETURN, recv, id, klass);
-	break;
-      }
-      case NODE_ATTRSET:{
-	if (argc != 1) {
-	    rb_raise(rb_eArgError, "wrong number of arguments (%d for 1)", argc);
-	}
-	val = rb_ivar_set(recv, body->nd_vid, argv[0]);
-	break;
-      }
-      case NODE_IVAR: {
-	if (argc != 0) {
-	    rb_raise(rb_eArgError, "wrong number of arguments (%d for 0)",
-		     argc);
-	}
-	val = rb_attr_get(recv, body->nd_vid);
-	break;
-      }
-      case NODE_BMETHOD:{
-	val = vm_call_bmethod(th, id, body->nd_cval,
-			      recv, klass, argc, (VALUE *)argv, blockptr);
-	break;
-      }
-      default:
-	rb_bug("unsupported: vm_call0(%s)", ruby_node_name(nd_type(body)));
-    }
-    RUBY_VM_CHECK_INTS();
-    return val;
-}
-
-static VALUE
-vm_call_super(rb_thread_t *th, int argc, const VALUE *argv)
-{
-    VALUE recv = th->cfp->self;
-    VALUE klass;
-    ID id;
-    NODE *body;
-    rb_control_frame_t *cfp = th->cfp;
-
-    if (!cfp->iseq) {
-	klass = cfp->method_class;
-	klass = RCLASS_SUPER(klass);
-
-	if (klass == 0) {
-	    klass = vm_search_normal_superclass(cfp->method_class, recv);
-	}
-
-	id = cfp->method_id;
-    }
-    else {
-	rb_bug("vm_call_super: should not be reached");
-    }
-
-    body = rb_method_node(klass, id);	/* this returns NODE_METHOD */
-
-    if (body) {
-	body = body->nd_body;
-    }
-    else {
-	dp(recv);
-	dp(klass);
-	dpi(id);
-	rb_bug("vm_call_super: not found");
-    }
-
-    return vm_call0(th, klass, recv, id, id, argc, argv, body, CALL_SUPER);
-}
-
-VALUE
-rb_call_super(int argc, const VALUE *argv)
-{
-    PASS_PASSED_BLOCK();
-    return vm_call_super(GET_THREAD(), argc, argv);
-}
-
 /* C -> Ruby: block */
 
-static VALUE
-invoke_block(rb_thread_t *th, rb_block_t *block, VALUE self,
-	     int argc, VALUE *argv, rb_block_t *blockptr)
+static inline VALUE
+invoke_block_from_c(rb_thread_t *th, const rb_block_t *block,
+		    VALUE self, int argc, const VALUE *argv,
+		    const rb_block_t *blockptr, const NODE *cref)
 {
-    VALUE val;
     if (BUILTIN_TYPE(block->iseq) != T_NODE) {
-	rb_iseq_t *iseq = block->iseq;
-	rb_control_frame_t *cfp = th->cfp;
-	int i, opt_pc;
-	const int arg_size = iseq->arg_size;
-	const int type = block_proc_is_lambda(block->proc) ? FRAME_MAGIC_LAMBDA : FRAME_MAGIC_BLOCK;
+	const rb_iseq_t *iseq = block->iseq;
+	const rb_control_frame_t *cfp = th->cfp;
+	int i, opt_pc, arg_size = iseq->arg_size;
+	int type = block_proc_is_lambda(block->proc) ? FRAME_MAGIC_LAMBDA : FRAME_MAGIC_BLOCK;
 
 	rb_vm_set_finish_env(th);
 
@@ -567,41 +441,56 @@
 		      iseq->iseq_encoded + opt_pc, cfp->sp + arg_size, block->lfp,
 		      iseq->local_size - arg_size);
 
-	val = vm_eval_body(th);
+	if (cref) {
+	    GC_WB(&th->cfp->dfp[-1], cref);
+	}
+
+	return vm_eval_body(th);
     }
     else {
-	val = vm_yield_with_cfunc(th, block, self, argc, argv);
+	return vm_yield_with_cfunc(th, block, self, argc, argv);
     }
-    return val;
 }
 
-VALUE
-vm_yield(rb_thread_t *th, int argc, VALUE *argv)
+static inline const rb_block_t *
+check_block(rb_thread_t *th)
 {
-    rb_block_t *block = GC_GUARDED_PTR_REF(th->cfp->lfp[0]);
+    const rb_block_t *blockptr = GC_GUARDED_PTR_REF(th->cfp->lfp[0]);
 
-    if (block == 0) {
+    if (blockptr == 0) {
 	vm_localjump_error("no block given", Qnil, 0);
     }
 
-    return invoke_block(th, block, block->self, argc, argv, 0);
+    return blockptr;
 }
 
+static inline VALUE
+vm_yield_with_cref(rb_thread_t *th, int argc, const VALUE *argv, const NODE *cref)
+{
+    const rb_block_t *blockptr = check_block(th);
+    return invoke_block_from_c(th, blockptr, blockptr->self, argc, argv, 0, cref);
+}
+
+static inline VALUE
+vm_yield(rb_thread_t *th, int argc, const VALUE *argv)
+{
+    const rb_block_t *blockptr = check_block(th);
+    return invoke_block_from_c(th, blockptr, blockptr->self, argc, argv, 0, 0);
+}
+
 VALUE
-vm_invoke_proc(rb_thread_t *th, rb_proc_t *proc,
-	       VALUE self, int argc, VALUE *argv, rb_block_t *blockptr)
+vm_invoke_proc(rb_thread_t *th, rb_proc_t *proc, VALUE self,
+	       int argc, const VALUE *argv, rb_block_t * blockptr)
 {
     VALUE val = Qundef;
     int state;
     volatile int stored_safe = th->safe_level;
-    volatile NODE *stored_special_cref_stack =
-      lfp_set_special_cref(proc->block.lfp, proc->special_cref_stack);
     rb_control_frame_t * volatile cfp = th->cfp;
 
     TH_PUSH_TAG(th);
     if ((state = EXEC_TAG()) == 0) {
 	th->safe_level = proc->safe_level;
-	val = invoke_block(th, &proc->block, self, argc, argv, blockptr);
+	val = invoke_block_from_c(th, &proc->block, self, argc, argv, blockptr, 0);
     }
     TH_POP_TAG();
 
@@ -609,8 +498,6 @@
 	th->safe_level = stored_safe;
     }
 
-    lfp_set_special_cref(proc->block.lfp, (NODE*)stored_special_cref_stack);
-
     if (state) {
 	if (state == TAG_RETURN && proc->is_lambda) {
 	    VALUE err = th->errinfo;
@@ -634,7 +521,7 @@
 
 /* special variable */
 
-VALUE
+static VALUE
 vm_cfp_svar_get(rb_thread_t *th, rb_control_frame_t *cfp, VALUE key)
 {
     while (cfp->pc == 0) {
@@ -643,8 +530,8 @@
     return lfp_svar_get(th, cfp->lfp, key);
 }
 
-void
-vm_cfp_svar_set(rb_thread_t *th, rb_control_frame_t *cfp, VALUE key, VALUE val)
+static void
+vm_cfp_svar_set(rb_thread_t *th, rb_control_frame_t *cfp, VALUE key, const VALUE val)
 {
     while (cfp->pc == 0) {
 	cfp++;
@@ -693,10 +580,10 @@
 /* backtrace */
 
 int
-vm_get_sourceline(rb_control_frame_t *cfp)
+vm_get_sourceline(const rb_control_frame_t *cfp)
 {
     int line_no = 0;
-    rb_iseq_t *iseq = cfp->iseq;
+    const rb_iseq_t *iseq = cfp->iseq;
 
     if (RUBY_VM_NORMAL_ISEQ_P(iseq)) {
 	int i;
@@ -716,9 +603,8 @@
 
 static VALUE
 vm_backtrace_each(rb_thread_t *th,
-		  rb_control_frame_t *limit_cfp,
-		  rb_control_frame_t *cfp,
-		  char *file, int line_no, VALUE ary)
+		  const rb_control_frame_t *limit_cfp, const rb_control_frame_t *cfp,
+		  const char * file, int line_no, VALUE ary)
 {
     VALUE str;
 
@@ -746,12 +632,12 @@
     return rb_ary_reverse(ary);
 }
 
-VALUE
+static inline VALUE
 vm_backtrace(rb_thread_t *th, int lev)
 {
     VALUE ary;
-    rb_control_frame_t *cfp = th->cfp;
-    rb_control_frame_t *top_of_cfp = (void *)(th->stack + th->stack_size);
+    const rb_control_frame_t *cfp = th->cfp;
+    const rb_control_frame_t *top_of_cfp = (void *)(th->stack + th->stack_size);
     top_of_cfp -= 2;
 
     if (lev < 0) {
@@ -773,48 +659,40 @@
     return ary;
 }
 
-/* cref */
-
-static void
-check_svar(void)
+const char *
+rb_sourcefile(void)
 {
     rb_thread_t *th = GET_THREAD();
-    rb_control_frame_t *cfp = th->cfp;
-    while ((void *)(cfp + 1) < (void *)(th->stack + th->stack_size)) {
-	/* printf("cfp: %p\n", cfp->type); */
-	if (cfp->lfp && cfp->lfp[-1] != Qnil &&
-	    TYPE(cfp->lfp[-1]) != T_VALUES) {
-	    /* dp(cfp->lfp[-1]); */
-	    rb_bug("!!!invalid svar!!!");
-	}
-	cfp++;
+    rb_control_frame_t *cfp = vm_get_ruby_level_cfp(th, th->cfp);
+
+    if (cfp) {
+	return RSTRING_CPTR(cfp->iseq->filename);
     }
+    else {
+	return 0;
+    }
 }
 
-static NODE *
-lfp_set_special_cref(VALUE *lfp, NODE * cref)
+int
+rb_sourceline(void)
 {
-    struct RValues *values = (void *) lfp[-1];
-    NODE *old_cref;
+    rb_thread_t *th = GET_THREAD();
+    rb_control_frame_t *cfp = vm_get_ruby_level_cfp(th, th->cfp);
 
-    if (VMDEBUG) {
-	check_svar();
+    if (cfp) {
+	return vm_get_sourceline(cfp);
     }
-
-    if (cref == 0 && ((VALUE)values == Qnil || values->basic.klass == 0)) {
-	old_cref = 0;
-    }
     else {
-	old_cref = (NODE *)lfp_svar_get(GET_THREAD(), lfp, 2);
-	lfp_svar_set(GET_THREAD(), lfp, 2, (VALUE)cref);
+	return 0;
     }
-    return old_cref;
 }
 
 NODE *
-vm_set_special_cref(rb_thread_t *th, VALUE *lfp, NODE * cref_stack)
+vm_cref(void)
 {
-    return lfp_set_special_cref(lfp, cref_stack);
+    rb_thread_t *th = GET_THREAD();
+    rb_control_frame_t *cfp = vm_get_ruby_level_cfp(th, th->cfp);
+    return vm_get_cref(cfp->iseq, cfp->lfp, cfp->dfp);
 }
 
 #if 0
@@ -829,29 +707,22 @@
 }
 #endif
 
-NODE *
-vm_get_cref(rb_thread_t *th, rb_iseq_t *iseq, rb_control_frame_t *cfp)
-{
-    return get_cref(iseq, cfp->lfp);
-}
-
-NODE *
+static NODE *
 vm_cref_push(rb_thread_t *th, VALUE klass, int noex)
 {
     NODE *cref = NEW_BLOCK(klass);
     rb_control_frame_t *cfp = vm_get_ruby_level_cfp(th, th->cfp);
 
     cref->nd_file = 0;
-    cref->nd_next = get_cref(cfp->iseq, cfp->lfp);
+    cref->nd_next = vm_get_cref(cfp->iseq, cfp->lfp, cfp->dfp);
     cref->nd_visi = noex;
     return cref;
 }
 
-VALUE
-vm_get_cbase(rb_thread_t *th)
+static inline VALUE
+vm_get_cbase(const rb_iseq_t *iseq, const VALUE *lfp, const VALUE *dfp)
 {
-    rb_control_frame_t *cfp = vm_get_ruby_level_cfp(th, th->cfp);
-    NODE *cref = get_cref(cfp->iseq, cfp->lfp);
+    NODE *cref = vm_get_cref(iseq, lfp, dfp);
     VALUE klass = Qundef;
 
     while (cref) {
@@ -860,9 +731,18 @@
 	}
 	cref = cref->nd_next;
     }
+
     return klass;
 }
 
+VALUE
+rb_vm_cbase(void)
+{
+    rb_thread_t *th = GET_THREAD();
+    rb_control_frame_t *cfp = vm_get_ruby_level_cfp(th, th->cfp);
+    return vm_get_cbase(cfp->iseq, cfp->lfp, cfp->dfp);
+}
+
 /* jump */
 
 static VALUE
@@ -960,7 +840,7 @@
 }
 
 void
-rb_iter_break()
+rb_iter_break(void)
 {
     vm_iter_break(GET_THREAD());
 }
@@ -970,8 +850,8 @@
 VALUE ruby_vm_redefined_flag = 0;
 static st_table *vm_opt_method_table = 0;
 
-void
-rb_vm_check_redefinition_opt_method(NODE *node)
+static void
+rb_vm_check_redefinition_opt_method(const NODE *node)
 {
     VALUE bop;
 
@@ -1043,16 +923,16 @@
   C1      : pushed by send insn (CFUNC)
 
   struct CONTROL_FRAME {
-    VALUE *pc;                  // cfp[0]
-    VALUE *sp;                  // cfp[1]
-    VALUE *bp;                  // cfp[2]
-    rb_iseq_t *iseq;            // cfp[3]
-    VALUE flag;                 // cfp[4]
-    VALUE self;                 // cfp[5]
-    VALUE *lfp;                 // cfp[6]
-    VALUE *dfp;                 // cfp[7]
-    rb_iseq_t * block_iseq;     // cfp[8]
-    VALUE proc;                 // cfp[9] always 0
+    VALUE *pc;                  // cfp[0], program counter
+    VALUE *sp;                  // cfp[1], stack pointer
+    VALUE *bp;                  // cfp[2], base pointer
+    rb_iseq_t *iseq;            // cfp[3], iseq
+    VALUE flag;                 // cfp[4], magic
+    VALUE self;                 // cfp[5], self
+    VALUE *lfp;                 // cfp[6], local frame pointer
+    VALUE *dfp;                 // cfp[7], dynamic frame pointer
+    rb_iseq_t * block_iseq;     // cfp[8], block iseq
+    VALUE proc;                 // cfp[9], always 0
   };
 
   struct BLOCK {
@@ -1060,15 +940,11 @@
     VALUE *lfp;
     VALUE *dfp;
     rb_iseq_t *block_iseq;
+    VALUE proc;
   };
 
-  struct PROC {
-    VALUE  proc_sig = 0;
-    struct BLOCK;
-  };
-
   struct METHOD_CONTROL_FRAME {
-    struct CONTROL_FRAME;
+    rb_control_frame_t frame;
   };
 
   struct METHOD_FRAME {
@@ -1078,12 +954,13 @@
     VALUE param0;
     ...
     VALUE paramN;
+    VALUE cref;
     VALUE special;                         // lfp [1]
     struct block_object *block_ptr | 0x01; // lfp [0]
   };
 
   struct BLOCK_CONTROL_FRAME {
-    struct STACK_FRAME;
+    rb_control_frame_t frame;
   };
 
   struct BLOCK_FRAME {
@@ -1093,17 +970,19 @@
     VALUE param0;
     ...
     VALUE paramN;
+    VALUE cref;
     VALUE *(prev_ptr | 0x01); // DFP[0]
   };
 
   struct CLASS_CONTROL_FRAME {
-    struct STACK_FRAME;
+    rb_control_frame_t frame;
   };
 
   struct CLASS_FRAME {
     VALUE param0;
     ...
     VALUE paramN;
+    VALUE cref;
     VALUE prev_dfp; // for frame jump
   };
 
@@ -1130,15 +1009,10 @@
     VALUE *dfp;                      // lfp
     rb_iseq_t * block_iseq; // 0
   };
-
-  struct C_METHDO_FRAME{
-    VALUE block_ptr;
-    VALUE special;
-  };
  */
 
 
-VALUE
+static VALUE
 vm_eval_body(rb_thread_t *th)
 {
     int state;
@@ -1267,9 +1141,7 @@
 			cfp->pc = cfp->iseq->iseq_encoded + entry->cont;
 			cfp->sp = cfp->bp + entry->sp;
 
-			if (!(state == TAG_REDO) &&
-			    !(state == TAG_NEXT && !escape_dfp) &&
-			    !(state == TAG_BREAK && !escape_dfp)) {
+			if (state != TAG_REDO) {
 #if OPT_STACK_CACHING
 			    initial = (GET_THROWOBJ_VAL(err));
 #else
@@ -1284,12 +1156,10 @@
 	}
 	else if (state == TAG_REDO) {
 	    type = CATCH_TYPE_REDO;
-	    escape_dfp = GET_THROWOBJ_CATCH_POINT(err);
 	    goto search_restart_point;
 	}
 	else if (state == TAG_NEXT) {
 	    type = CATCH_TYPE_NEXT;
-	    escape_dfp = GET_THROWOBJ_CATCH_POINT(err);
 	    goto search_restart_point;
 	}
 	else {
@@ -1320,7 +1190,7 @@
 	    cfp->sp[0] = err;
 	    vm_push_frame(th, catch_iseq, FRAME_MAGIC_BLOCK,
 			  cfp->self, (VALUE)cfp->dfp, catch_iseq->iseq_encoded,
-			  cfp->sp + 1, cfp->lfp, catch_iseq->local_size - 1);
+			  cfp->sp + 1 /* push value */, cfp->lfp, catch_iseq->local_size - 1);
 
 	    state = 0;
 	    th->errinfo = Qnil;
@@ -1353,7 +1223,7 @@
     VALUE val;
     volatile VALUE tmp;
 
-    rb_vm_set_top_stack(th, iseqval);
+    vm_set_top_stack(th, iseqval);
 
     if (!rb_const_defined(rb_cObject, rb_intern("TOPLEVEL_BINDING"))) {
 	rb_define_global_const("TOPLEVEL_BINDING", rb_binding_new());
@@ -1364,7 +1234,8 @@
 }
 
 int
-rb_thread_method_id_and_class(rb_thread_t *th, ID *idp, VALUE *klassp)
+rb_thread_method_id_and_class(rb_thread_t *th,
+			      ID *idp, VALUE *klassp)
 {
     rb_control_frame_t *cfp = th->cfp;
     rb_iseq_t *iseq = cfp->iseq;
@@ -1399,9 +1270,9 @@
 }
 
 VALUE
-rb_thread_current_status(rb_thread_t *th)
+rb_thread_current_status(const rb_thread_t *th)
 {
-    rb_control_frame_t *cfp = th->cfp;
+    const rb_control_frame_t *cfp = th->cfp;
     VALUE str = Qnil;
 
     if (cfp->iseq != 0) {
@@ -1423,15 +1294,17 @@
 }
 
 VALUE
-rb_vm_call_cfunc(VALUE recv, VALUE (*func)(VALUE), VALUE arg, rb_block_t *blockptr, VALUE filename)
+rb_vm_call_cfunc(VALUE recv, VALUE (*func)(VALUE), VALUE arg,
+		 const rb_block_t *blockptr, VALUE filename)
 {
     rb_thread_t *th = GET_THREAD();
-    rb_control_frame_t *reg_cfp = th->cfp;
+    const rb_control_frame_t *reg_cfp = th->cfp;
     volatile VALUE iseqval = rb_iseq_new(0, filename, filename, 0, ISEQ_TYPE_TOP);
     VALUE val;
 
     vm_push_frame(th, DATA_PTR(iseqval), FRAME_MAGIC_TOP,
 		  recv, (VALUE)blockptr, 0, reg_cfp->sp, 0, 1);
+
     val = (*func)(arg);
 
     vm_pop_frame(th);
@@ -1439,7 +1312,7 @@
 }
 
 int
-rb_vm_cfunc_funcall_p(rb_control_frame_t *cfp)
+rb_vm_cfunc_funcall_p(const rb_control_frame_t *cfp)
 {
     if (vm_cfunc_flags(cfp) & (VM_CALL_FCALL_BIT | VM_CALL_VCALL_BIT))
 	return Qtrue;
@@ -1468,7 +1341,9 @@
 static int
 vm_mark_each_thread_func(st_data_t key, st_data_t value, st_data_t dummy)
 {
+#if !WITH_OBJC
     VALUE thval = (VALUE)key;
+#endif
     rb_gc_mark(thval);
     return ST_CONTINUE;
 }
@@ -1558,6 +1433,7 @@
 #endif
 }
 
+#ifdef USE_THREAD_RECYCLE
 static rb_thread_t *
 thread_recycle_struct(void)
 {
@@ -1565,6 +1441,7 @@
     memset(p, 0, sizeof(rb_thread_t));
     return p;
 }
+#endif
 
 static void
 thread_free(void *ptr)
@@ -1737,6 +1614,8 @@
 extern VALUE *rb_gc_register_stack_start;
 #endif
 
+/* debug functions */
+
 static VALUE
 sdr(void)
 {
@@ -1784,7 +1663,6 @@
     /* ::Thread */
     rb_cThread = rb_define_class("Thread", rb_cObject);
     rb_undef_alloc_func(rb_cThread);
-    rb_define_method(rb_cThread, "initialize", ruby_thread_init, 0);
 
     /* ::VM::USAGE_ANALYSIS_* */
     rb_define_const(rb_cVM, "USAGE_ANALYSIS_INSN", rb_hash_new());
@@ -1824,8 +1702,13 @@
     rb_define_const(rb_cVM, "INSTRUCTION_NAMES", insns_name_array());
 
     /* debug functions ::VM::SDR(), ::VM::NSDR() */
-    /* rb_define_singleton_method(rb_cVM, "SDR", sdr, 0); */
-    /* rb_define_singleton_method(rb_cVM, "NSDR", nsdr, 0); */
+#if VMDEBUG
+    rb_define_singleton_method(rb_cVM, "SDR", sdr, 0);
+    rb_define_singleton_method(rb_cVM, "NSDR", nsdr, 0);
+#else
+    (void)sdr;
+    (void)nsdr;
+#endif
 
     /* VM bootstrap: phase 2 */
     {
@@ -1912,13 +1795,13 @@
 }
 
 VALUE
-rb_vm_top_self()
+rb_vm_top_self(void)
 {
     return GET_VM()->top_self;
 }
 
 void
-Init_top_self()
+Init_top_self(void)
 {
     rb_vm_t *vm = GET_VM();
 

Modified: MacRuby/branches/testing/vm.h
===================================================================
--- MacRuby/branches/testing/vm.h	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/vm.h	2008-06-05 08:33:02 UTC (rev 249)
@@ -2,7 +2,7 @@
 
   vm.h -
 
-  $Author: ko1 $
+  $Author: nobu $
   created at: 04/01/01 16:56:59 JST
 
   Copyright (C) 2004-2007 Koichi Sasada
@@ -13,7 +13,6 @@
 #define RUBY_VM_H
 
 typedef long OFFSET;
-typedef unsigned long rb_num_t;
 typedef unsigned long lindex_t;
 typedef unsigned long dindex_t;
 typedef rb_num_t GENTRY;

Modified: MacRuby/branches/testing/vm_core.h
===================================================================
--- MacRuby/branches/testing/vm_core.h	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/vm_core.h	2008-06-05 08:33:02 UTC (rev 249)
@@ -17,6 +17,7 @@
 #include <setjmp.h>
 
 #include "ruby/ruby.h"
+#include "ruby/mvm.h"
 #include "ruby/signal.h"
 #include "ruby/st.h"
 #include "ruby/node.h"
@@ -88,6 +89,8 @@
 #define UNLIKELY(x) (x)
 #endif /* __GNUC__ >= 3 */
 
+typedef unsigned long rb_num_t;
+
 #define ISEQ_TYPE_TOP    INT2FIX(1)
 #define ISEQ_TYPE_METHOD INT2FIX(2)
 #define ISEQ_TYPE_BLOCK  INT2FIX(3)
@@ -283,7 +286,8 @@
 #define GetVMPtr(obj, ptr) \
   GetCoreDataFromValue(obj, rb_vm_t, ptr)
 
-typedef struct rb_vm_struct {
+struct rb_vm_struct
+{
     VALUE self;
 
     rb_thread_lock_t global_interpreter_lock;
@@ -295,6 +299,7 @@
     VALUE thgroup_default;
     VALUE last_status; /* $? */
 
+    int running;
     int thread_abort_on_exception;
     unsigned long trace_flag;
 
@@ -317,7 +322,7 @@
 #if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE
     struct rb_objspace *objspace;
 #endif
-} rb_vm_t;
+};
 
 typedef struct {
     VALUE *pc;			/* cfp[0] */
@@ -370,7 +375,10 @@
 #define RUBY_VM_VALUE_CACHE_SIZE 0x1000
 #define USE_VALUE_CACHE 0
 
-typedef struct rb_thread_struct rb_thread_t;
+struct rb_unblock_callback {
+    rb_unblock_function_t *func;
+    void *arg;
+};
 
 struct rb_thread_struct
 {
@@ -415,9 +423,8 @@
     int exec_signal;
 
     int interrupt_flag;
-    rb_unblock_function_t *unblock_function;
-    void *unblock_function_arg;
     rb_thread_lock_t interrupt_lock;
+    struct rb_unblock_callback unblock;
 
     struct rb_vm_tag *tag;
     struct rb_vm_trap_tag *trap_tag;
@@ -447,7 +454,6 @@
     VALUE *machine_register_stack_end;
     size_t machine_register_stack_maxsize;
 #endif
-
     jmp_buf machine_regs;
     int mark_stack_len;
 
@@ -498,8 +504,6 @@
     int safe_level;
     int is_from_method;
     int is_lambda;
-
-    NODE *special_cref_stack;
 } rb_proc_t;
 
 #define GetEnvPtr(obj, ptr) \
@@ -518,7 +522,6 @@
 
 typedef struct {
     VALUE env;
-    NODE *cref_stack;
 } rb_binding_t;
 
 
@@ -607,19 +610,11 @@
 void rb_disable_interrupt(void);
 int rb_thread_method_id_and_class(rb_thread_t *th, ID *idp, VALUE *klassp);
 
-VALUE vm_eval_body(rb_thread_t *th);
 VALUE vm_invoke_proc(rb_thread_t *th, rb_proc_t *proc, VALUE self,
-		     int argc, VALUE *argv, rb_block_t *blockptr);
-VALUE vm_make_proc(rb_thread_t *th, rb_control_frame_t *cfp, rb_block_t *block);
+		     int argc, const VALUE *argv, rb_block_t *blockptr);
+VALUE vm_make_proc(rb_thread_t *th, rb_control_frame_t *cfp, const rb_block_t *block);
 VALUE vm_make_env_object(rb_thread_t *th, rb_control_frame_t *cfp);
-VALUE vm_backtrace(rb_thread_t *, int);
 
-VALUE vm_yield(rb_thread_t *th, int argc, VALUE *argv);
-VALUE vm_call0(rb_thread_t *th, VALUE klass, VALUE recv, VALUE id, ID oid,
-	       int argc, const VALUE *argv, NODE *body, int nosuper);
-
-int vm_get_sourceline(rb_control_frame_t *);
-
 NOINLINE(void rb_gc_save_machine_context(rb_thread_t *));
 
 RUBY_EXTERN VALUE sysstack_error;

Modified: MacRuby/branches/testing/vm_dump.c
===================================================================
--- MacRuby/branches/testing/vm_dump.c	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/vm_dump.c	2008-06-05 08:33:02 UTC (rev 249)
@@ -2,7 +2,7 @@
 
   vm_dump.c -
 
-  $Author: akr $
+  $Author: naruse $
 
   Copyright (C) 2004-2007 Koichi Sasada
 
@@ -21,8 +21,8 @@
 control_frame_dump(rb_thread_t *th, rb_control_frame_t *cfp)
 {
     int pc = -1, bp = -1, line = 0;
-    unsigned int lfp = cfp->lfp - th->stack;
-    unsigned int dfp = cfp->dfp - th->stack;
+    ptrdiff_t lfp = cfp->lfp - th->stack;
+    ptrdiff_t dfp = cfp->dfp - th->stack;
     char lfp_in_heap = ' ', dfp_in_heap = ' ';
     char posbuf[MAX_POSBUF+1];
 
@@ -34,11 +34,11 @@
     }
 
     if (lfp < 0 || lfp > th->stack_size) {
-	lfp = (unsigned int)cfp->lfp;
+	lfp = (ptrdiff_t)cfp->lfp;
 	lfp_in_heap = 'p';
     }
     if (dfp < 0 || dfp > th->stack_size) {
-	dfp = (unsigned int)cfp->dfp;
+	dfp = (ptrdiff_t)cfp->dfp;
 	dfp_in_heap = 'p';
     }
     if (cfp->bp) {
@@ -97,6 +97,8 @@
 	    iseq_name = "<ifunc>";
 	}
 	else {
+	    int vm_get_sourceline(rb_control_frame_t *);
+
 	    pc = cfp->pc - cfp->iseq->iseq_encoded;
 	    iseq_name = RSTRING_CPTR(cfp->iseq->name);
 	    line = vm_get_sourceline(cfp);
@@ -113,7 +115,7 @@
 	line = -1;
     }
 
-    fprintf(stderr, "c:%04d ",
+    fprintf(stderr, "c:%04td ",
 	    (rb_control_frame_t *)(th->stack + th->stack_size) - cfp);
     if (pc == -1) {
 	fprintf(stderr, "p:---- ");
@@ -121,9 +123,9 @@
     else {
 	fprintf(stderr, "p:%04d ", pc);
     }
-    fprintf(stderr, "s:%04d b:%04d ", cfp->sp - th->stack, bp);
-    fprintf(stderr, lfp_in_heap == ' ' ? "l:%06d " : "l:%06x ", lfp % 10000);
-    fprintf(stderr, dfp_in_heap == ' ' ? "d:%06d " : "d:%06x ", dfp % 10000);
+    fprintf(stderr, "s:%04td b:%04d ", cfp->sp - th->stack, bp);
+    fprintf(stderr, lfp_in_heap == ' ' ? "l:%06td " : "l:%06tx ", lfp % 10000);
+    fprintf(stderr, dfp_in_heap == ' ' ? "d:%06td " : "d:%06tx ", dfp % 10000);
     fprintf(stderr, "%-6s ", magic);
     if (line) {
 	fprintf(stderr, "%s", posbuf);
@@ -140,7 +142,7 @@
 void
 vm_stack_dump_raw(rb_thread_t *th, rb_control_frame_t *cfp)
 {
-#if 0
+#if 1
     VALUE *sp = cfp->sp, *bp = cfp->bp;
     VALUE *lfp = cfp->lfp;
     VALUE *dfp = cfp->dfp;
@@ -148,11 +150,11 @@
 
     fprintf(stderr, "-- stack frame ------------\n");
     for (p = st = th->stack; p < sp; p++) {
-	fprintf(stderr, "%04ld (%p): %08lx", p - st, p, *p);
+	fprintf(stderr, "%04ld (%p): %08"PRIxVALUE, (long)(p - st), p, *p);
 
 	t = (VALUE *)*p;
 	if (th->stack <= t && t < sp) {
-	    fprintf(stderr, " (= %ld)", (VALUE *)GC_GUARDED_PTR_REF(t) - th->stack);
+	    fprintf(stderr, " (= %ld)", (long)((VALUE *)GC_GUARDED_PTR_REF(t) - th->stack));
 	}
 
 	if (p == lfp)
@@ -175,6 +177,13 @@
 }
 
 void
+vm_stack_dump_raw_current(void)
+{
+    rb_thread_t *th = GET_THREAD();
+    vm_stack_dump_raw(th, th->cfp);
+}
+
+void
 env_dump_raw(rb_env_t *env, VALUE *lfp, VALUE *dfp)
 {
     int i;
@@ -299,7 +308,7 @@
 	    else {
 		rstr = rb_inspect(*ptr);
 	    }
-	    fprintf(stderr, "  stack %2d: %8s (%d)\n", i, StringValueCStr(rstr),
+	    fprintf(stderr, "  stack %2d: %8s (%td)\n", i, StringValueCStr(rstr),
 		   ptr - th->stack);
 	}
     }
@@ -336,7 +345,7 @@
 	dfp = -1;
 
     cfpi = ((rb_control_frame_t *)(th->stack + th->stack_size)) - cfp;
-    fprintf(stderr, "  [PC] %04d, [SP] %04d, [LFP] %04d, [DFP] %04d, [CFP] %04d\n",
+    fprintf(stderr, "  [PC] %04d, [SP] %04td, [LFP] %04d, [DFP] %04d, [CFP] %04d\n",
 	   pc, cfp->sp - th->stack, lfp, dfp, cfpi);
 }
 
@@ -357,7 +366,7 @@
 	VALUE *seq = iseq->iseq;
 	int pc = cfp->pc - iseq->iseq_encoded;
 
-	printf("%3d ", VM_CFP_CNT(th, cfp));
+	printf("%3td ", VM_CFP_CNT(th, cfp));
 	ruby_iseq_disasm_insn(0, seq, pc, iseq, 0);
     }
 
@@ -562,17 +571,18 @@
     return Qnil;
 }
 
+VALUE rb_make_backtrace(void);
+
 void
 rb_vm_bugreport(void)
 {
-    rb_thread_t *th = GET_THREAD();
     VALUE bt;
 
     if (GET_THREAD()->vm) {
 	int i;
 	SDR();
 
-	bt = vm_backtrace(th, 0);
+	bt = rb_make_backtrace();
 	if (TYPE(bt) == T_ARRAY)
 	for (i = 0; i < RARRAY_LEN(bt); i++) {
 	    dp(RARRAY_AT(bt, i));

Copied: MacRuby/branches/testing/vm_eval.c (from rev 248, MacRuby/trunk/vm_eval.c)
===================================================================
--- MacRuby/branches/testing/vm_eval.c	                        (rev 0)
+++ MacRuby/branches/testing/vm_eval.c	2008-06-05 08:33:02 UTC (rev 249)
@@ -0,0 +1,1344 @@
+/**********************************************************************
+
+  vm_eval.c -
+
+  $Author: nobu $
+  created at: Sat May 24 16:02:32 JST 2008
+
+  Copyright (C) 1993-2007 Yukihiro Matsumoto
+  Copyright (C) 2000  Network Applied Communication Laboratory, Inc.
+  Copyright (C) 2000  Information-technology Promotion Agency, Japan
+
+**********************************************************************/
+
+#include "ruby/ruby.h"
+#include "ruby/node.h"
+#include "ruby/st.h"
+
+#include "vm_method.c"
+
+static inline VALUE method_missing(VALUE obj, ID id, int argc, const VALUE *argv, int call_status);
+static inline VALUE rb_vm_set_finish_env(rb_thread_t * th);
+static inline VALUE vm_yield_with_cref(rb_thread_t *th, int argc, const VALUE *argv, const NODE *cref);
+static inline VALUE vm_yield(rb_thread_t *th, int argc, const VALUE *argv);
+static inline VALUE vm_backtrace(rb_thread_t *th, int lev);
+static NODE *vm_cref_push(rb_thread_t *th, VALUE klass, int noex);
+static VALUE vm_eval_body(rb_thread_t *th);
+static void vm_set_eval_stack(rb_thread_t * th, VALUE iseqval, const NODE *cref);
+
+static inline VALUE
+vm_call0(rb_thread_t * th, VALUE klass, VALUE recv, VALUE id, ID oid,
+	 int argc, const VALUE *argv, const NODE *body, int nosuper)
+{
+    VALUE val;
+    rb_block_t *blockptr = 0;
+
+    if (0) printf("id: %s, nd: %s, argc: %d, passed: %p\n",
+		  rb_id2name(id), ruby_node_name(nd_type(body)),
+		  argc, th->passed_block);
+
+    if (th->passed_block) {
+	blockptr = th->passed_block;
+	th->passed_block = 0;
+    }
+    switch (nd_type(body)) {
+      case RUBY_VM_METHOD_NODE:{
+	rb_control_frame_t *reg_cfp;
+	VALUE iseqval = (VALUE)body->nd_body;
+	int i;
+
+	rb_vm_set_finish_env(th);
+	reg_cfp = th->cfp;
+
+	CHECK_STACK_OVERFLOW(reg_cfp, argc + 1);
+
+	*reg_cfp->sp++ = recv;
+	for (i = 0; i < argc; i++) {
+	    *reg_cfp->sp++ = argv[i];
+	}
+
+	vm_setup_method(th, reg_cfp, argc, blockptr, 0, iseqval, recv, klass);
+	val = vm_eval_body(th);
+	break;
+      }
+      case NODE_CFUNC: {
+	EXEC_EVENT_HOOK(th, RUBY_EVENT_C_CALL, recv, id, klass);
+	{
+	    rb_control_frame_t *reg_cfp = th->cfp;
+	    rb_control_frame_t *cfp =
+		vm_push_frame(th, 0, FRAME_MAGIC_CFUNC,
+			      recv, (VALUE)blockptr, 0, reg_cfp->sp, 0, 1);
+
+	    cfp->method_id = id;
+	    cfp->method_class = klass;
+
+	    val = call_cfunc(body->nd_cfnc, recv, body->nd_argc, argc, argv);
+
+	    if (reg_cfp != th->cfp + 1) {
+		SDR2(reg_cfp);
+		SDR2(th->cfp-5);
+		rb_bug("cfp consistency error - call0");
+		th->cfp = reg_cfp;
+	    }
+	    vm_pop_frame(th);
+	}
+	EXEC_EVENT_HOOK(th, RUBY_EVENT_C_RETURN, recv, id, klass);
+	break;
+      }
+      case NODE_ATTRSET:{
+	if (argc != 1) {
+	    rb_raise(rb_eArgError, "wrong number of arguments (%d for 1)", argc);
+	}
+	val = rb_ivar_set(recv, body->nd_vid, argv[0]);
+	break;
+      }
+      case NODE_IVAR: {
+	if (argc != 0) {
+	    rb_raise(rb_eArgError, "wrong number of arguments (%d for 0)",
+		     argc);
+	}
+	val = rb_attr_get(recv, body->nd_vid);
+	break;
+      }
+      case NODE_BMETHOD:{
+	val = vm_call_bmethod(th, id, body->nd_cval,
+			      recv, klass, argc, (VALUE *)argv, blockptr);
+	break;
+      }
+      default:
+	rb_bug("unsupported: vm_call0(%s)", ruby_node_name(nd_type(body)));
+    }
+    RUBY_VM_CHECK_INTS();
+    return val;
+}
+
+VALUE
+rb_vm_call(rb_thread_t * th, VALUE klass, VALUE recv, VALUE id, ID oid,
+	   int argc, const VALUE *argv, const NODE *body, int nosuper)
+{
+    return vm_call0(th, klass, recv, id, oid, argc, argv, body, nosuper);
+}
+
+static inline VALUE
+vm_call_super(rb_thread_t * const th, const int argc, const VALUE * const argv)
+{
+    VALUE recv = th->cfp->self;
+    VALUE klass;
+    ID id;
+    NODE *body;
+    rb_control_frame_t *cfp = th->cfp;
+
+    if (!cfp->iseq) {
+	klass = cfp->method_class;
+	klass = RCLASS_SUPER(klass);
+
+	if (klass == 0) {
+	    klass = vm_search_normal_superclass(cfp->method_class, recv);
+	}
+
+	id = cfp->method_id;
+    }
+    else {
+	rb_bug("vm_call_super: should not be reached");
+    }
+
+    body = rb_method_node(klass, id);	/* this returns NODE_METHOD */
+
+    if (body) {
+	body = body->nd_body;
+    }
+    else {
+	dp(recv);
+	dp(klass);
+	dpi(id);
+	rb_bug("vm_call_super: not found");
+    }
+
+    return vm_call0(th, klass, recv, id, id, argc, argv, body, CALL_SUPER);
+}
+
+VALUE
+rb_call_super(int argc, const VALUE *argv)
+{
+    PASS_PASSED_BLOCK();
+    return vm_call_super(GET_THREAD(), argc, argv);
+}
+
+static inline void
+stack_check(void)
+{
+    rb_thread_t *th = GET_THREAD();
+
+    if (!rb_thread_raised_p(th, RAISED_STACKOVERFLOW) && ruby_stack_check()) {
+	rb_thread_raised_set(th, RAISED_STACKOVERFLOW);
+	rb_exc_raise(sysstack_error);
+    }
+}
+
+static inline VALUE
+rb_call0(VALUE klass, VALUE recv, ID mid, int argc, const VALUE *argv,
+	 int scope, VALUE self)
+{
+    NODE *body, *method;
+    int noex;
+    ID id = mid;
+    struct cache_entry *ent;
+    rb_thread_t *th = GET_THREAD();
+#if WITH_OBJC
+    unsigned redo = 0;
+#endif
+
+rb_call0_redo:
+
+#if WITH_OBJC
+# define REDO_PERHAPS() \
+    do { \
+	if (!redo && mid != missing) { \
+	    ID newid = rb_objc_missing_sel(mid, argc); \
+	    if (newid != mid) { \
+		id = mid = newid; \
+		redo = 1; \
+		goto rb_call0_redo; \
+	    } \
+	} \
+    } \
+    while (0)
+#else
+# define REDO_PERHAPS()
+#endif
+
+    if (!klass) {
+	rb_raise(rb_eNotImpError,
+		 "method `%s' called on terminated object (%p)",
+		 rb_id2name(mid), (void *)recv);
+    }
+    /* is it in the method cache? */
+    ent = cache + EXPR1(klass, mid);
+
+    if (ent->mid == mid && ent->klass == klass) {
+	if (!ent->method) {
+	    REDO_PERHAPS();
+	    return method_missing(recv, mid, argc, argv,
+				  scope == 2 ? NOEX_VCALL : 0);
+	}
+	id = ent->mid0;
+	noex = ent->method->nd_noex;
+	klass = ent->method->nd_clss;
+	body = ent->method->nd_body;
+    }
+    else if ((method = rb_get_method_body(klass, id, &id)) != 0) {
+	noex = method->nd_noex;
+	klass = method->nd_clss;
+	body = method->nd_body;
+    }
+    else {
+	REDO_PERHAPS();
+	if (scope == 3) {
+	    return method_missing(recv, mid, argc, argv, NOEX_SUPER);
+	}
+	return method_missing(recv, mid, argc, argv,
+			      scope == 2 ? NOEX_VCALL : 0);
+    }
+    
+
+    if (mid != missing) {
+	/* receiver specified form for private method */
+	if (UNLIKELY(noex)) {
+	    if (((noex & NOEX_MASK) & NOEX_PRIVATE) && scope == 0) {
+		return method_missing(recv, mid, argc, argv, NOEX_PRIVATE);
+	    }
+
+	    /* self must be kind of a specified form for protected method */
+	    if (((noex & NOEX_MASK) & NOEX_PROTECTED) && scope == 0) {
+		VALUE defined_class = klass;
+		
+		if (TYPE(defined_class) == T_ICLASS) {
+		    defined_class = RBASIC(defined_class)->klass;
+		}
+
+		if (self == Qundef) {
+		    self = th->cfp->self;
+		}
+		if (!rb_obj_is_kind_of(self, rb_class_real(defined_class))) {
+		    return method_missing(recv, mid, argc, argv, NOEX_PROTECTED);
+		}
+	    }
+
+	    if (NOEX_SAFE(noex) > th->safe_level) {
+		rb_raise(rb_eSecurityError, "calling insecure method: %s", rb_id2name(mid));
+	    }
+	}
+    }
+
+    stack_check();
+    return vm_call0(th, klass, recv, mid, id, argc, argv, body, noex & NOEX_NOSUPER);
+}
+
+static inline VALUE
+rb_call(VALUE klass, VALUE recv, ID mid, int argc, const VALUE *argv, int scope)
+{
+    return rb_call0(klass, recv, mid, argc, argv, scope, Qundef);
+}
+
+/*
+ *  call-seq:
+ *     obj.method_missing(symbol [, *args] )   => result
+ *
+ *  Invoked by Ruby when <i>obj</i> is sent a message it cannot handle.
+ *  <i>symbol</i> is the symbol for the method called, and <i>args</i>
+ *  are any arguments that were passed to it. By default, the interpreter
+ *  raises an error when this method is called. However, it is possible
+ *  to override the method to provide more dynamic behavior.
+ *  If it is decided that a particular method should not be handled, then
+ *  <i>super</i> should be called, so that ancestors can pick up the
+ *  missing method.
+ *  The example below creates
+ *  a class <code>Roman</code>, which responds to methods with names
+ *  consisting of roman numerals, returning the corresponding integer
+ *  values.
+ *
+ *     class Roman
+ *       def romanToInt(str)
+ *         # ...
+ *       end
+ *       def method_missing(methId)
+ *         str = methId.id2name
+ *         romanToInt(str)
+ *       end
+ *     end
+ *
+ *     r = Roman.new
+ *     r.iv      #=> 4
+ *     r.xxiii   #=> 23
+ *     r.mm      #=> 2000
+ */
+
+static VALUE
+rb_method_missing(int argc, const VALUE *argv, VALUE obj)
+{
+    ID id;
+    VALUE exc = rb_eNoMethodError;
+    const char *format = 0;
+    rb_thread_t *th = GET_THREAD();
+    int last_call_status = th->method_missing_reason;
+    if (argc == 0 || !SYMBOL_P(argv[0])) {
+	rb_raise(rb_eArgError, "no id given");
+    }
+
+    stack_check();
+
+    id = SYM2ID(argv[0]);
+
+    if (last_call_status & NOEX_PRIVATE) {
+	format = "private method `%s' called for %s";
+    }
+    else if (last_call_status & NOEX_PROTECTED) {
+	format = "protected method `%s' called for %s";
+    }
+    else if (last_call_status & NOEX_VCALL) {
+	format = "undefined local variable or method `%s' for %s";
+	exc = rb_eNameError;
+    }
+    else if (last_call_status & NOEX_SUPER) {
+	format = "super: no superclass method `%s' for %s";
+    }
+    if (!format) {
+	format = "undefined method `%s' for %s";
+    }
+
+    {
+	int n = 0;
+	VALUE args[3];
+	args[n++] = rb_funcall(rb_const_get(exc, rb_intern("message")), '!',
+			       3, rb_str_new2(format), obj, argv[0]);
+	args[n++] = argv[0];
+	if (exc == rb_eNoMethodError) {
+	    args[n++] = rb_ary_new4(argc - 1, argv + 1);
+	}
+	exc = rb_class_new_instance(n, args, exc);
+
+	th->cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(th->cfp);
+	rb_exc_raise(exc);
+    }
+
+    return Qnil;		/* not reached */
+}
+
+static inline VALUE
+method_missing(VALUE obj, ID id, int argc, const VALUE *argv, int call_status)
+{
+    VALUE *nargv;
+    GET_THREAD()->method_missing_reason = call_status;
+
+    if (id == missing) {
+	rb_method_missing(argc, argv, obj);
+    }
+    else if (id == ID_ALLOCATOR) {
+	rb_raise(rb_eTypeError, "allocator undefined for %s",
+		 rb_class2name(obj));
+    }
+
+    nargv = ALLOCA_N(VALUE, argc + 1);
+    nargv[0] = ID2SYM(id);
+    MEMCPY(nargv + 1, argv, VALUE, argc);
+
+    return rb_funcall2(obj, missing, argc + 1, nargv);
+}
+
+VALUE
+rb_apply(VALUE recv, ID mid, VALUE args)
+{
+    int argc;
+    VALUE *argv;
+
+    argc = RARRAY_LEN(args);	/* Assigns LONG, but argc is INT */
+    argv = ALLOCA_N(VALUE, argc);
+    MEMCPY(argv, RARRAY_PTR(args), VALUE, argc);
+    return rb_call(CLASS_OF(recv), recv, mid, argc, argv, CALL_FCALL);
+}
+
+VALUE
+rb_funcall(VALUE recv, ID mid, int n, ...)
+{
+    VALUE *argv;
+    va_list ar;
+    va_init_list(ar, n);
+
+    if (n > 0) {
+	long i;
+
+	argv = ALLOCA_N(VALUE, n);
+
+	for (i = 0; i < n; i++) {
+	    argv[i] = va_arg(ar, VALUE);
+	}
+	va_end(ar);
+    }
+    else {
+	argv = 0;
+    }
+    return rb_call(CLASS_OF(recv), recv, mid, n, argv, CALL_FCALL);
+}
+
+VALUE
+rb_funcall2(VALUE recv, ID mid, int argc, const VALUE *argv)
+{
+    return rb_call(CLASS_OF(recv), recv, mid, argc, argv, CALL_FCALL);
+}
+
+VALUE
+rb_funcall3(VALUE recv, ID mid, int argc, const VALUE *argv)
+{
+    return rb_call(CLASS_OF(recv), recv, mid, argc, argv, CALL_PUBLIC);
+}
+
+static VALUE
+send_internal(int argc, VALUE *argv, VALUE recv, int scope)
+{
+    VALUE vid;
+    VALUE self = RUBY_VM_PREVIOUS_CONTROL_FRAME(GET_THREAD()->cfp)->self;
+
+    if (argc == 0) {
+	rb_raise(rb_eArgError, "no method name given");
+    }
+
+    vid = *argv++; argc--;
+    PASS_PASSED_BLOCK();
+    return rb_call0(CLASS_OF(recv), recv, rb_to_id(vid), argc, argv, scope, self);
+}
+
+/*
+ *  call-seq:
+ *     obj.send(symbol [, args...])        => obj
+ *     obj.__send__(symbol [, args...])      => obj
+ *
+ *  Invokes the method identified by _symbol_, passing it any
+ *  arguments specified. You can use <code>__send__</code> if the name
+ *  +send+ clashes with an existing method in _obj_.
+ *
+ *     class Klass
+ *       def hello(*args)
+ *         "Hello " + args.join(' ')
+ *       end
+ *     end
+ *     k = Klass.new
+ *     k.send :hello, "gentle", "readers"   #=> "Hello gentle readers"
+ */
+
+VALUE
+rb_f_send(int argc, VALUE *argv, VALUE recv)
+{
+    return send_internal(argc, argv, recv, NOEX_NOSUPER | NOEX_PRIVATE);
+}
+
+/*
+ *  call-seq:
+ *     obj.public_send(symbol [, args...])  => obj
+ *
+ *  Invokes the method identified by _symbol_, passing it any
+ *  arguments specified. Unlike send, public_send calls public
+ *  methods only.
+ *
+ *     1.public_send(:puts, "hello")  # causes NoMethodError
+ */
+
+VALUE
+rb_f_public_send(int argc, VALUE *argv, VALUE recv)
+{
+    return send_internal(argc, argv, recv, NOEX_PUBLIC);
+}
+
+/* yield */
+
+static inline VALUE
+rb_yield_0(int argc, const VALUE * argv)
+{
+    return vm_yield(GET_THREAD(), argc, argv);
+}
+
+VALUE
+rb_yield(VALUE val)
+{
+    if (val == Qundef) {
+	return rb_yield_0(0, 0);
+    }
+    else {
+	return rb_yield_0(1, &val);
+    }
+}
+
+VALUE
+rb_yield_values(int n, ...)
+{
+    if (n == 0) {
+	return rb_yield_0(0, 0);
+    }
+    else {
+	int i;
+	VALUE *argv;
+	va_list args;
+	argv = ALLOCA_N(VALUE, n);
+
+	va_init_list(args, n);
+	for (i=0; i<n; i++) {
+	    argv[i] = va_arg(args, VALUE);
+	}
+	va_end(args);
+
+	return rb_yield_0(n, argv);
+    }
+}
+
+VALUE
+rb_yield_values2(int argc, const VALUE *argv)
+{
+    return rb_yield_0(argc, argv);
+}
+
+VALUE
+rb_yield_splat(VALUE values)
+{
+    VALUE tmp = rb_check_array_type(values);
+    volatile VALUE v;
+    if (NIL_P(tmp)) {
+        rb_raise(rb_eArgError, "not an array");
+    }
+    v = rb_yield_0(RARRAY_LEN(tmp), RARRAY_PTR(tmp));
+    return v;
+}
+
+static VALUE
+loop_i(void)
+{
+    for (;;) {
+	rb_yield_0(0, 0);
+    }
+    return Qnil;
+}
+
+/*
+ *  call-seq:
+ *     loop {|| block }
+ *
+ *  Repeatedly executes the block.
+ *
+ *     loop do
+ *       print "Input: "
+ *       line = gets
+ *       break if !line or line =~ /^qQ/
+ *       # ...
+ *     end
+ *
+ *  StopIteration raised in the block breaks the loop.
+ */
+
+static VALUE
+rb_f_loop(void)
+{
+    rb_rescue2(loop_i, (VALUE)0, 0, 0, rb_eStopIteration, (VALUE)0);
+    return Qnil;		/* dummy */
+}
+
+VALUE
+rb_iterate(VALUE (* it_proc) (VALUE), VALUE data1,
+	   VALUE (* bl_proc) (ANYARGS), VALUE data2)
+{
+    int state;
+    volatile VALUE retval = Qnil;
+    NODE *node = NEW_IFUNC(bl_proc, data2);
+    rb_thread_t *th = GET_THREAD();
+    rb_control_frame_t *cfp = th->cfp;
+
+    TH_PUSH_TAG(th);
+    state = TH_EXEC_TAG();
+    if (state == 0) {
+      iter_retry:
+	{
+	    rb_block_t *blockptr = RUBY_VM_GET_BLOCK_PTR_IN_CFP(th->cfp);
+	    blockptr->iseq = (void *)node;
+	    blockptr->proc = 0;
+	    th->passed_block = blockptr;
+	}
+	retval = (*it_proc) (data1);
+    }
+    else {
+	VALUE err = th->errinfo;
+	if (state == TAG_BREAK) {
+	    VALUE *escape_dfp = GET_THROWOBJ_CATCH_POINT(err);
+	    VALUE *cdfp = cfp->dfp;
+
+	    if (cdfp == escape_dfp) {
+		state = 0;
+		th->state = 0;
+		th->errinfo = Qnil;
+		th->cfp = cfp;
+	    }
+	    else{
+		/* SDR(); printf("%p, %p\n", cdfp, escape_dfp); */
+	    }
+	}
+	else if (state == TAG_RETRY) {
+	    VALUE *escape_dfp = GET_THROWOBJ_CATCH_POINT(err);
+	    VALUE *cdfp = cfp->dfp;
+
+	    if (cdfp == escape_dfp) {
+		state = 0;
+		th->state = 0;
+		th->errinfo = Qnil;
+		th->cfp = cfp;
+		goto iter_retry;
+	    }
+	}
+    }
+    TH_POP_TAG();
+
+    switch (state) {
+      case 0:
+	break;
+      default:
+	TH_JUMP_TAG(th, state);
+    }
+    return retval;
+}
+
+struct iter_method_arg {
+    VALUE obj;
+    ID mid;
+    int argc;
+    VALUE *argv;
+};
+
+static VALUE
+iterate_method(VALUE obj)
+{
+    const struct iter_method_arg * arg =
+      (struct iter_method_arg *) obj;
+
+    return rb_call(CLASS_OF(arg->obj), arg->obj, arg->mid,
+		   arg->argc, arg->argv, CALL_FCALL);
+}
+
+VALUE
+rb_block_call(VALUE obj, ID mid, int argc, VALUE * argv,
+	      VALUE (*bl_proc) (ANYARGS), VALUE data2)
+{
+    struct iter_method_arg arg;
+
+    arg.obj = obj;
+    arg.mid = mid;
+    arg.argc = argc;
+    arg.argv = argv;
+    return rb_iterate(iterate_method, (VALUE)&arg, bl_proc, data2);
+}
+
+VALUE
+rb_each(VALUE obj)
+{
+    return rb_call(CLASS_OF(obj), obj, idEach, 0, 0, CALL_FCALL);
+}
+
+static VALUE
+eval_string_with_cref(VALUE self, VALUE src, VALUE scope, NODE *cref, const char *file, int line)
+{
+    int state;
+    VALUE result = Qundef;
+    VALUE envval;
+    rb_binding_t *bind = 0;
+    rb_thread_t *th = GET_THREAD();
+    rb_env_t *env = NULL;
+    rb_block_t block;
+
+    if (file == 0) {
+	file = rb_sourcefile();
+	line = rb_sourceline();
+    }
+
+    PUSH_TAG();
+    if ((state = EXEC_TAG()) == 0) {
+	rb_iseq_t *iseq;
+	volatile VALUE iseqval;
+
+	if (scope != Qnil) {
+	    if (rb_obj_is_kind_of(scope, rb_cBinding)) {
+		GetBindingPtr(scope, bind);
+		envval = bind->env;
+	    }
+	    else {
+		rb_raise(rb_eTypeError,
+			 "wrong argument type %s (expected Binding)",
+			 rb_obj_classname(scope));
+	    }
+	    GetEnvPtr(envval, env);
+	    th->base_block = &env->block;
+	}
+	else {
+	    rb_control_frame_t *cfp = vm_get_ruby_level_cfp(th, th->cfp);
+	    block = *RUBY_VM_GET_BLOCK_PTR_IN_CFP(cfp);
+	    th->base_block = &block;
+	    th->base_block->self = self;
+	    th->base_block->iseq = cfp->iseq;	/* TODO */
+	}
+
+	/* make eval iseq */
+	th->parse_in_eval++;
+	iseqval = rb_iseq_compile(src, rb_str_new2(file), INT2FIX(line));
+	th->parse_in_eval--;
+
+	vm_set_eval_stack(th, iseqval, cref);
+	th->base_block = 0;
+
+	if (0) {		/* for debug */
+	    extern VALUE ruby_iseq_disasm(VALUE);
+	    printf("%s\n", RSTRING_CPTR(ruby_iseq_disasm(iseqval)));
+	}
+
+	/* save new env */
+	GetISeqPtr(iseqval, iseq);
+	if (bind && iseq->local_size > 0) {
+	    bind->env = vm_make_env_object(th, th->cfp);
+	}
+
+	/* kick */
+	CHECK_STACK_OVERFLOW(th->cfp, iseq->stack_max);
+	result = vm_eval_body(th);
+    }
+    POP_TAG();
+
+    if (state) {
+	if (state == TAG_RAISE) {
+	    VALUE errinfo = th->errinfo;
+	    if (strcmp(file, "(eval)") == 0) {
+		VALUE mesg, errat, bt2;
+		extern VALUE rb_get_backtrace(VALUE info);
+
+		errat = rb_get_backtrace(errinfo);
+		mesg = rb_attr_get(errinfo, rb_intern("mesg"));
+		if (!NIL_P(errat) && TYPE(errat) == T_ARRAY &&
+		    (bt2 = vm_backtrace(th, -2), RARRAY_LEN(bt2) > 0)) {
+		    if (!NIL_P(mesg) && TYPE(mesg) == T_STRING && !RSTRING_CLEN(mesg)) {
+			rb_str_update(mesg, 0, 0, rb_str_new2(": "));
+			rb_str_update(mesg, 0, 0, RARRAY_AT(errat, 0));
+		    }
+		    rb_ary_store(errat, 0, RARRAY_AT(bt2, 0));
+		}
+	    }
+	    rb_exc_raise(errinfo);
+	}
+	JUMP_TAG(state);
+    }
+    return result;
+}
+
+static VALUE
+eval_string(VALUE self, VALUE src, VALUE scope, const char *file, int line)
+{
+    return eval_string_with_cref(self, src, scope, 0, file, line);
+}
+
+/*
+ *  call-seq:
+ *     eval(string [, binding [, filename [,lineno]]])  => obj
+ *
+ *  Evaluates the Ruby expression(s) in <em>string</em>. If
+ *  <em>binding</em> is given, the evaluation is performed in its
+ *  context. The binding may be a <code>Binding</code> object or a
+ *  <code>Proc</code> object. If the optional <em>filename</em> and
+ *  <em>lineno</em> parameters are present, they will be used when
+ *  reporting syntax errors.
+ *
+ *     def getBinding(str)
+ *       return binding
+ *     end
+ *     str = "hello"
+ *     eval "str + ' Fred'"                      #=> "hello Fred"
+ *     eval "str + ' Fred'", getBinding("bye")   #=> "bye Fred"
+ */
+
+VALUE
+rb_f_eval(int argc, VALUE *argv, VALUE self)
+{
+    VALUE src, scope, vfile, vline;
+    const char *file = "(eval)";
+    int line = 1;
+
+    rb_scan_args(argc, argv, "13", &src, &scope, &vfile, &vline);
+    if (rb_safe_level() >= 4) {
+	StringValue(src);
+	if (!NIL_P(scope) && !OBJ_TAINTED(scope)) {
+	    rb_raise(rb_eSecurityError,
+		     "Insecure: can't modify trusted binding");
+	}
+    }
+    else {
+	SafeStringValue(src);
+    }
+    if (argc >= 3) {
+	StringValue(vfile);
+    }
+    if (argc >= 4) {
+	line = NUM2INT(vline);
+    }
+
+    if (!NIL_P(vfile))
+	file = RSTRING_CPTR(vfile);
+    return eval_string(self, src, scope, file, line);
+}
+
+VALUE
+rb_eval_string(const char *str)
+{
+    return eval_string(rb_vm_top_self(), rb_str_new2(str), Qnil, "(eval)", 1);
+}
+
+VALUE
+rb_eval_string_protect(const char *str, int *state)
+{
+    return rb_protect((VALUE (*)(VALUE))rb_eval_string, (VALUE)str, state);
+}
+
+VALUE
+rb_eval_string_wrap(const char *str, int *state)
+{
+    int status;
+    rb_thread_t *th = GET_THREAD();
+    VALUE self = th->top_self;
+    VALUE wrapper = th->top_wrapper;
+    VALUE val;
+
+    th->top_wrapper = rb_module_new();
+    th->top_self = rb_obj_clone(rb_vm_top_self());
+    rb_extend_object(th->top_self, th->top_wrapper);
+
+    val = rb_eval_string_protect(str, &status);
+
+    th->top_self = self;
+    th->top_wrapper = wrapper;
+
+    if (state) {
+	*state = status;
+    }
+    else if (status) {
+	JUMP_TAG(status);
+    }
+    return val;
+}
+
+VALUE
+rb_eval_cmd(VALUE cmd, VALUE arg, int level)
+{
+    int state;
+    VALUE val = Qnil;		/* OK */
+    volatile int safe = rb_safe_level();
+
+    if (OBJ_TAINTED(cmd)) {
+	level = 4;
+    }
+
+    if (TYPE(cmd) != T_STRING) {
+	PUSH_TAG();
+	rb_set_safe_level_force(level);
+	if ((state = EXEC_TAG()) == 0) {
+	    val = rb_funcall2(cmd, rb_intern("call"), RARRAY_LEN(arg),
+			      RARRAY_PTR(arg));
+	}
+	POP_TAG();
+
+	rb_set_safe_level_force(safe);
+
+	if (state)
+	  JUMP_TAG(state);
+	return val;
+    }
+
+    PUSH_TAG();
+    if ((state = EXEC_TAG()) == 0) {
+	val = eval_string(rb_vm_top_self(), cmd, Qnil, 0, 0);
+    }
+    POP_TAG();
+
+    rb_set_safe_level_force(safe);
+    if (state) vm_jump_tag_but_local_jump(state, val);
+    return val;
+}
+
+/* block eval under the class/module context */
+
+static VALUE
+yield_under(VALUE under, VALUE self, VALUE values)
+{
+    rb_thread_t *th = GET_THREAD();
+    rb_block_t block, *blockptr;
+    NODE *cref = vm_cref_push(th, under, NOEX_PUBLIC);
+
+    if ((blockptr = GC_GUARDED_PTR_REF(th->cfp->lfp[0])) != 0) {
+	block = *blockptr;
+	block.self = self;
+	th->cfp->lfp[0] = GC_GUARDED_PTR(&block);
+    }
+
+    if (values == Qundef) {
+	return vm_yield_with_cref(th, 0, 0, cref);
+    }
+    else {
+	return vm_yield_with_cref(th, RARRAY_LEN(values), RARRAY_PTR(values), cref);
+    }
+}
+
+/* string eval under the class/module context */
+static VALUE
+eval_under(VALUE under, VALUE self, VALUE src, const char *file, int line)
+{
+    NODE *cref = vm_cref_push(GET_THREAD(), under, NOEX_PUBLIC);
+
+    if (rb_safe_level() >= 4) {
+	StringValue(src);
+    }
+    else {
+	SafeStringValue(src);
+    }
+
+    return eval_string_with_cref(self, src, Qnil, cref, file, line);
+}
+
+static VALUE
+specific_eval(int argc, VALUE *argv, VALUE klass, VALUE self)
+{
+    if (rb_block_given_p()) {
+	if (argc > 0) {
+	    rb_raise(rb_eArgError, "wrong number of arguments (%d for 0)", argc);
+	}
+	return yield_under(klass, self, Qundef);
+    }
+    else {
+	const char *file = "(eval)";
+	int line = 1;
+
+	if (argc == 0) {
+	    rb_raise(rb_eArgError, "block not supplied");
+	}
+	else {
+	    if (rb_safe_level() >= 4) {
+		StringValue(argv[0]);
+	    }
+	    else {
+		SafeStringValue(argv[0]);
+	    }
+	    if (argc > 3) {
+		const char *name = rb_id2name(rb_frame_callee());
+		rb_raise(rb_eArgError,
+			 "wrong number of arguments: %s(src) or %s{..}",
+			 name, name);
+	    }
+	    if (argc > 2)
+		line = NUM2INT(argv[2]);
+	    if (argc > 1) {
+		file = StringValuePtr(argv[1]);
+	    }
+	}
+	return eval_under(klass, self, argv[0], file, line);
+    }
+}
+
+/*
+ *  call-seq:
+ *     obj.instance_eval(string [, filename [, lineno]] )   => obj
+ *     obj.instance_eval {| | block }                       => obj
+ *
+ *  Evaluates a string containing Ruby source code, or the given block,
+ *  within the context of the receiver (_obj_). In order to set the
+ *  context, the variable +self+ is set to _obj_ while
+ *  the code is executing, giving the code access to _obj_'s
+ *  instance variables. In the version of <code>instance_eval</code>
+ *  that takes a +String+, the optional second and third
+ *  parameters supply a filename and starting line number that are used
+ *  when reporting compilation errors.
+ *
+ *     class KlassWithSecret
+ *       def initialize
+ *         @secret = 99
+ *       end
+ *     end
+ *     k = KlassWithSecret.new
+ *     k.instance_eval { @secret }   #=> 99
+ */
+
+VALUE
+rb_obj_instance_eval(int argc, VALUE *argv, VALUE self)
+{
+    VALUE klass;
+
+    if (SPECIAL_CONST_P(self)) {
+	klass = Qnil;
+    }
+    else {
+	klass = rb_singleton_class(self);
+    }
+    return specific_eval(argc, argv, klass, self);
+}
+
+/*
+ *  call-seq:
+ *     obj.instance_exec(arg...) {|var...| block }                       => obj
+ *
+ *  Executes the given block within the context of the receiver
+ *  (_obj_). In order to set the context, the variable +self+ is set
+ *  to _obj_ while the code is executing, giving the code access to
+ *  _obj_'s instance variables.  Arguments are passed as block parameters.
+ *
+ *     class KlassWithSecret
+ *       def initialize
+ *         @secret = 99
+ *       end
+ *     end
+ *     k = KlassWithSecret.new
+ *     k.instance_exec(5) {|x| @secret+x }   #=> 104
+ */
+
+VALUE
+rb_obj_instance_exec(int argc, VALUE *argv, VALUE self)
+{
+    VALUE klass;
+
+    if (SPECIAL_CONST_P(self)) {
+	klass = Qnil;
+    }
+    else {
+	klass = rb_singleton_class(self);
+    }
+    return yield_under(klass, self, rb_ary_new4(argc, argv));
+}
+
+/*
+ *  call-seq:
+ *     mod.class_eval(string [, filename [, lineno]])  => obj
+ *     mod.module_eval {|| block }                     => obj
+ *
+ *  Evaluates the string or block in the context of _mod_. This can
+ *  be used to add methods to a class. <code>module_eval</code> returns
+ *  the result of evaluating its argument. The optional _filename_
+ *  and _lineno_ parameters set the text for error messages.
+ *
+ *     class Thing
+ *     end
+ *     a = %q{def hello() "Hello there!" end}
+ *     Thing.module_eval(a)
+ *     puts Thing.new.hello()
+ *     Thing.module_eval("invalid code", "dummy", 123)
+ *
+ *  <em>produces:</em>
+ *
+ *     Hello there!
+ *     dummy:123:in `module_eval': undefined local variable
+ *         or method `code' for Thing:Class
+ */
+
+VALUE
+rb_mod_module_eval(int argc, VALUE *argv, VALUE mod)
+{
+    return specific_eval(argc, argv, mod, mod);
+}
+
+/*
+ *  call-seq:
+ *     mod.module_exec(arg...) {|var...| block }       => obj
+ *     mod.class_exec(arg...) {|var...| block }        => obj
+ *
+ *  Evaluates the given block in the context of the class/module.
+ *  The method defined in the block will belong to the receiver.
+ *
+ *     class Thing
+ *     end
+ *     Thing.class_exec{
+ *       def hello() "Hello there!" end
+ *     }
+ *     puts Thing.new.hello()
+ *
+ *  <em>produces:</em>
+ *
+ *     Hello there!
+ */
+
+VALUE
+rb_mod_module_exec(int argc, VALUE *argv, VALUE mod)
+{
+    return yield_under(mod, mod, rb_ary_new4(argc, argv));
+}
+
+NORETURN(static VALUE rb_f_throw _((int, VALUE *)));
+
+/*
+ *  call-seq:
+ *     throw(symbol [, obj])
+ *
+ *  Transfers control to the end of the active +catch+ block
+ *  waiting for _symbol_. Raises +NameError+ if there
+ *  is no +catch+ block for the symbol. The optional second
+ *  parameter supplies a return value for the +catch+ block,
+ *  which otherwise defaults to +nil+. For examples, see
+ *  <code>Kernel::catch</code>.
+ */
+
+static VALUE
+rb_f_throw(int argc, VALUE *argv)
+{
+    VALUE tag, value;
+    rb_thread_t *th = GET_THREAD();
+    struct rb_vm_tag *tt = th->tag;
+
+    rb_scan_args(argc, argv, "11", &tag, &value);
+    while (tt) {
+	if (tt->tag == tag) {
+	    tt->retval = value;
+	    break;
+	}
+	tt = tt->prev;
+    }
+    if (!tt) {
+	VALUE desc = rb_inspect(tag);
+	rb_raise(rb_eArgError, "uncaught throw %s", RSTRING_CPTR(desc));
+    }
+    rb_trap_restore_mask();
+    th->errinfo = NEW_THROW_OBJECT(tag, 0, TAG_THROW);
+
+    JUMP_TAG(TAG_THROW);
+#ifndef __GNUC__
+    return Qnil;		/* not reached */
+#endif
+}
+
+void
+rb_throw(const char *tag, VALUE val)
+{
+    VALUE argv[2];
+
+    argv[0] = ID2SYM(rb_intern(tag));
+    argv[1] = val;
+    rb_f_throw(2, argv);
+}
+
+void
+rb_throw_obj(VALUE tag, VALUE val)
+{
+    VALUE argv[2];
+
+    argv[0] = tag;
+    argv[1] = val;
+    rb_f_throw(2, argv);
+}
+
+/*
+ *  call-seq:
+ *     catch(symbol) {| | block }  > obj
+ *
+ *  +catch+ executes its block. If a +throw+ is
+ *  executed, Ruby searches up its stack for a +catch+ block
+ *  with a tag corresponding to the +throw+'s
+ *  _symbol_. If found, that block is terminated, and
+ *  +catch+ returns the value given to +throw+. If
+ *  +throw+ is not called, the block terminates normally, and
+ *  the value of +catch+ is the value of the last expression
+ *  evaluated. +catch+ expressions may be nested, and the
+ *  +throw+ call need not be in lexical scope.
+ *
+ *     def routine(n)
+ *       puts n
+ *       throw :done if n <= 0
+ *       routine(n-1)
+ *     end
+ *
+ *
+ *     catch(:done) { routine(3) }
+ *
+ *  <em>produces:</em>
+ *
+ *     3
+ *     2
+ *     1
+ *     0
+ */
+
+static VALUE
+rb_f_catch(int argc, VALUE *argv)
+{
+    VALUE tag;
+    int state;
+    VALUE val = Qnil;		/* OK */
+    rb_thread_t *th = GET_THREAD();
+    rb_control_frame_t *saved_cfp = th->cfp;
+
+    if (argc == 0) {
+	tag = rb_obj_alloc(rb_cObject);
+    }
+    else {
+	rb_scan_args(argc, argv, "01", &tag);
+    }
+    PUSH_TAG();
+
+    th->tag->tag = tag;
+
+    if ((state = EXEC_TAG()) == 0) {
+	val = rb_yield_0(1, &tag);
+    }
+    else if (state == TAG_THROW && RNODE(th->errinfo)->u1.value == tag) {
+	th->cfp = saved_cfp;
+	val = th->tag->retval;
+	th->errinfo = Qnil;
+	state = 0;
+    }
+    POP_TAG();
+    if (state)
+	JUMP_TAG(state);
+
+    return val;
+}
+
+static VALUE
+catch_null_i(VALUE dmy)
+{
+    return rb_funcall(Qnil, rb_intern("catch"), 0, 0);
+}
+
+static VALUE
+catch_i(VALUE tag)
+{
+    return rb_funcall(Qnil, rb_intern("catch"), 1, tag);
+}
+
+VALUE
+rb_catch(const char *tag, VALUE (*func)(), VALUE data)
+{
+    if (!tag) {
+	return rb_iterate(catch_null_i, 0, func, data);
+    }
+    return rb_iterate(catch_i, ID2SYM(rb_intern(tag)), func, data);
+}
+
+VALUE
+rb_catch_obj(VALUE tag, VALUE (*func)(), VALUE data)
+{
+    return rb_iterate((VALUE (*)_((VALUE)))catch_i, tag, func, data);
+}
+
+/*
+ *  call-seq:
+ *     caller(start=1)    => array
+ *
+ *  Returns the current execution stack---an array containing strings in
+ *  the form ``<em>file:line</em>'' or ``<em>file:line: in
+ *  `method'</em>''. The optional _start_ parameter
+ *  determines the number of initial stack entries to omit from the
+ *  result.
+ *
+ *     def a(skip)
+ *       caller(skip)
+ *     end
+ *     def b(skip)
+ *       a(skip)
+ *     end
+ *     def c(skip)
+ *       b(skip)
+ *     end
+ *     c(0)   #=> ["prog:2:in `a'", "prog:5:in `b'", "prog:8:in `c'", "prog:10"]
+ *     c(1)   #=> ["prog:5:in `b'", "prog:8:in `c'", "prog:11"]
+ *     c(2)   #=> ["prog:8:in `c'", "prog:12"]
+ *     c(3)   #=> ["prog:13"]
+ */
+
+static VALUE
+rb_f_caller(int argc, VALUE *argv)
+{
+    VALUE level;
+    int lev;
+
+    rb_scan_args(argc, argv, "01", &level);
+
+    if (NIL_P(level))
+	lev = 1;
+    else
+	lev = NUM2INT(level);
+    if (lev < 0)
+	rb_raise(rb_eArgError, "negative level (%d)", lev);
+
+    return vm_backtrace(GET_THREAD(), lev);
+}
+
+void
+rb_backtrace(void)
+{
+    long i;
+    VALUE ary;
+
+    ary = vm_backtrace(GET_THREAD(), -1);
+    for (i = 0; i < RARRAY_LEN(ary); i++) {
+	printf("\tfrom %s\n", RSTRING_CPTR(RARRAY_AT(ary, i)));
+    }
+}
+
+VALUE
+rb_make_backtrace(void)
+{
+    return vm_backtrace(GET_THREAD(), -1);
+}
+
+void
+Init_vm_eval(void)
+{
+    rb_define_global_function("catch", rb_f_catch, -1);
+    rb_define_global_function("throw", rb_f_throw, -1);
+
+    rb_define_global_function("loop", rb_f_loop, 0);
+
+    rb_define_method(rb_cBasicObject, "instance_eval", rb_obj_instance_eval, -1);
+    rb_define_method(rb_cBasicObject, "instance_exec", rb_obj_instance_exec, -1);
+    rb_define_private_method(rb_cBasicObject, "method_missing", rb_method_missing, -1);
+
+    rb_define_method(rb_cBasicObject, "__send__", rb_f_send, -1);
+    rb_define_method(rb_mKernel, "send", rb_f_send, -1);
+    rb_define_method(rb_mKernel, "public_send", rb_f_public_send, -1);
+
+    rb_define_method(rb_cModule, "module_exec", rb_mod_module_exec, -1);
+    rb_define_method(rb_cModule, "class_exec", rb_mod_module_exec, -1);
+
+    rb_define_global_function("caller", rb_f_caller, -1);
+}
+

Modified: MacRuby/branches/testing/vm_evalbody.c
===================================================================
--- MacRuby/branches/testing/vm_evalbody.c	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/vm_evalbody.c	2008-06-05 08:33:02 UTC (rev 249)
@@ -3,7 +3,7 @@
 
   vm_evalbody.c -
 
-  $Author: shyouhei $
+  $Author: ko1 $
 
   Copyright (C) 2004-2007 Koichi Sasada
 
@@ -26,7 +26,7 @@
 /* #define DECL_SC_REG(r, reg) VALUE reg_##r */
 
 #if !OPT_CALL_THREADED_CODE
-VALUE
+static VALUE
 vm_eval(rb_thread_t *th, VALUE initial)
 {
 
@@ -140,3 +140,9 @@
     return ret;
 }
 #endif
+
+const void **
+vm_get_insns_address_table(void)
+{
+    return (const void **)vm_eval(0, 0);
+}

Modified: MacRuby/branches/testing/vm_insnhelper.c
===================================================================
--- MacRuby/branches/testing/vm_insnhelper.c	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/vm_insnhelper.c	2008-06-05 08:33:02 UTC (rev 249)
@@ -2,7 +2,7 @@
 
   insnhelper.c - instruction helper functions.
 
-  $Author: matz $
+  $Author: ko1 $
 
   Copyright (C) 2007 Koichi Sasada
 
@@ -21,14 +21,16 @@
 #endif
 
 static inline rb_control_frame_t *
-vm_push_frame(rb_thread_t *th, rb_iseq_t *iseq, VALUE type,
-	      VALUE self, VALUE specval, VALUE *pc,
-	      VALUE *sp, VALUE *lfp, int local_size)
+vm_push_frame(rb_thread_t * th, const rb_iseq_t * iseq,
+	      VALUE type, VALUE self, VALUE specval,
+	      const VALUE *pc, VALUE *sp, VALUE *lfp,
+	      int local_size)
 {
-    VALUE *dfp;
-    rb_control_frame_t *cfp;
+    rb_control_frame_t * const cfp = th->cfp = th->cfp - 1;
     int i;
 
+    /* setup vm value stack */
+    
     /* nil initialize */
     for (i=0; i < local_size; i++) {
 	*sp = Qnil;
@@ -37,21 +39,21 @@
 
     /* set special val */
     *sp = GC_GUARDED_PTR(specval);
-    dfp = sp;
 
     if (lfp == 0) {
 	lfp = sp;
     }
 
-    cfp = th->cfp = th->cfp - 1;
-    cfp->pc = pc;
+    /* setup vm control frame stack */
+
+    cfp->pc = (VALUE *)pc;
     cfp->sp = sp + 1;
     cfp->bp = sp + 1;
-    cfp->iseq = iseq;
+    cfp->iseq = (rb_iseq_t *) iseq;
     cfp->flag = type;
     cfp->self = self;
     cfp->lfp = lfp;
-    cfp->dfp = dfp;
+    cfp->dfp = sp;
     cfp->proc = 0;
 
 #define COLLECT_PROFILE 0
@@ -96,24 +98,25 @@
 
 /* method dispatch */
 
-static int
-vm_callee_setup_arg(rb_thread_t *th, rb_iseq_t *iseq,
-		    int argc, VALUE *argv, rb_block_t **block)
+static inline int
+vm_callee_setup_arg(rb_thread_t *th, const rb_iseq_t * iseq,
+		    int orig_argc, VALUE * orig_argv, const rb_block_t **block)
 {
     const int m = iseq->argc;
-    const int orig_argc = argc;
 
     if (LIKELY(iseq->arg_simple & 0x01)) {
 	/* simple check */
-	if (argc != m) {
+	if (orig_argc != m) {
 	    rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)",
-		     argc, m);
+		     orig_argc, m);
 	}
 	return 0;
     }
     else {
-	VALUE * const dst = argv;
+	int argc = orig_argc;
+	VALUE *argv = orig_argv;
 	int opt_pc = 0;
+
 	th->mark_stack_len = argc + iseq->arg_size;
 
 	/* mandatory */
@@ -133,7 +136,7 @@
 		argv = new_argv;
 	    }
 
-	    MEMCPY(&dst[iseq->arg_post_start], &argv[argc -= iseq->arg_post_len],
+	    MEMCPY(&orig_argv[iseq->arg_post_start], &argv[argc -= iseq->arg_post_len],
 		   VALUE, iseq->arg_post_len);
 	}
 
@@ -154,7 +157,7 @@
 	    else {
 		int i;
 		for (i = argc; i<opts; i++) {
-		    dst[i + m] = Qnil;
+		    orig_argv[i + m] = Qnil;
 		}
 		opt_pc = iseq->arg_opt_table[argc];
 		argc = 0;
@@ -163,14 +166,14 @@
 
 	/* rest arguments */
 	if (iseq->arg_rest != -1) {
-	    dst[iseq->arg_rest] = rb_ary_new4(argc, argv);
+	    orig_argv[iseq->arg_rest] = rb_ary_new4(argc, argv);
 	    argc = 0;
 	}
 
 	/* block arguments */
 	if (block && iseq->arg_block != -1) {
 	    VALUE blockval = Qnil;
-	    rb_block_t * const blockptr = *block;
+	    const rb_block_t *blockptr = *block;
 
 	    if (argc != 0) {
 		rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)",
@@ -192,7 +195,7 @@
 		}
 	    }
 
-	    dst[iseq->arg_block] = blockval; /* Proc or nil */
+	    orig_argv[iseq->arg_block] = blockval; /* Proc or nil */
 	}
 
 	th->mark_stack_len = 0;
@@ -201,7 +204,7 @@
 }
 
 static inline int
-caller_setup_args(rb_thread_t *th, rb_control_frame_t *cfp, VALUE flag,
+caller_setup_args(const rb_thread_t *th, rb_control_frame_t *cfp, VALUE flag,
 		  int argc, rb_iseq_t *blockiseq, rb_block_t **block)
 {
     rb_block_t *blockptr = 0;
@@ -263,7 +266,8 @@
 }
 
 static inline VALUE
-call_cfunc(VALUE (*func)(), VALUE recv, int len, int argc, const VALUE *argv)
+call_cfunc(VALUE (*func)(), VALUE recv,
+	   int len, int argc, const VALUE *argv)
 {
     /* printf("len: %d, argc: %d\n", len, argc); */
 
@@ -350,9 +354,9 @@
 }
 
 static inline VALUE
-vm_call_cfunc(rb_thread_t *th, rb_control_frame_t *reg_cfp, int num,
-	      ID id, VALUE recv, VALUE klass, VALUE flag,
-	      NODE *mn, rb_block_t *blockptr)
+vm_call_cfunc(rb_thread_t *th, rb_control_frame_t *reg_cfp,
+	      int num, ID id, VALUE recv, VALUE klass,
+	      VALUE flag, const NODE *mn, const rb_block_t *blockptr)
 {
     VALUE val;
 
@@ -379,8 +383,8 @@
     return val;
 }
 
-static int
-vm_cfunc_flags(rb_control_frame_t *cfp)
+static inline int
+vm_cfunc_flags(const rb_control_frame_t *cfp)
 {
     if (RUBYVM_CFUNC_FRAME_P(cfp))
 	return cfp->flag >> FRAME_MAGIC_MASK_BITS;
@@ -405,10 +409,10 @@
 }
 
 static inline VALUE
-vm_method_missing(rb_thread_t *th, ID id, VALUE recv, int num,
-		  rb_block_t *blockptr, int opt)
+vm_method_missing(rb_thread_t *th, ID id, VALUE recv,
+		  int num, rb_block_t *blockptr, int opt)
 {
-    rb_control_frame_t *reg_cfp = th->cfp;
+    rb_control_frame_t * const reg_cfp = th->cfp;
     VALUE *argv = STACK_ADDR_FROM_TOP(num + 1);
     VALUE val;
     argv[0] = ID2SYM(id);
@@ -421,8 +425,8 @@
 
 static inline void
 vm_setup_method(rb_thread_t *th, rb_control_frame_t *cfp,
-		int argc, rb_block_t *blockptr, VALUE flag,
-		VALUE iseqval, VALUE recv, VALUE klass)
+		const int argc, const rb_block_t *blockptr, const VALUE flag,
+		const VALUE iseqval, const VALUE recv, const VALUE klass)
 {
     rb_iseq_t *iseq;
     int opt_pc, i;
@@ -454,7 +458,7 @@
     }
     else {
 	VALUE *p_rsp;
-	cfp = ++th->cfp; /* pop cf */
+	th->cfp++; /* pop cf */
 	p_rsp = th->cfp->sp;
 
 	/* copy arguments */
@@ -476,15 +480,15 @@
 }
 
 static inline VALUE
-vm_call_method(rb_thread_t *th, rb_control_frame_t *cfp,
-	       int num, rb_block_t *blockptr, VALUE flag,
-	       ID id, NODE *mn, VALUE recv, VALUE klass)
+vm_call_method(rb_thread_t * const th, rb_control_frame_t * const cfp,
+	       const int num, rb_block_t * const blockptr, const VALUE flag,
+	       const ID id, const NODE * mn, const VALUE recv, VALUE klass)
 {
     VALUE val;
 
   start_method_dispatch:
 
-    if ((mn != 0)) {
+    if (mn != 0) {
 	if ((mn->nd_noex == 0)) {
 	    /* dispatch method */
 	    NODE *node;
@@ -606,8 +610,9 @@
 }
 
 static inline void
-vm_send_optimize(rb_control_frame_t *reg_cfp,
-		 NODE **mn, rb_num_t *flag, rb_num_t *num, ID *id, VALUE klass)
+vm_send_optimize(rb_control_frame_t * const reg_cfp, NODE ** const mn,
+		 rb_num_t * const flag, rb_num_t * const num,
+		 ID * const id, const VALUE klass)
 {
     if (*mn && nd_type((*mn)->nd_body) == NODE_CFUNC) {
 	NODE *node = (*mn)->nd_body;
@@ -634,7 +639,7 @@
 /* yield */
 
 static inline int
-block_proc_is_lambda(VALUE procval)
+block_proc_is_lambda(const VALUE procval)
 {
     rb_proc_t *proc;
 
@@ -648,8 +653,8 @@
 }
 
 static inline VALUE
-vm_yield_with_cfunc(rb_thread_t *th, rb_block_t *block,
-		    VALUE self, int argc, VALUE *argv)
+vm_yield_with_cfunc(rb_thread_t *th, const rb_block_t *block,
+		    VALUE self, int argc, const VALUE *argv)
 {
     NODE *ifunc = (NODE *) block->iseq;
     VALUE val;
@@ -677,11 +682,12 @@
 }
 
 static inline int
-vm_yield_setup_args(rb_thread_t *th, rb_iseq_t *iseq,
-		    int argc, VALUE *argv, rb_block_t *blockptr, int lambda)
+vm_yield_setup_args(rb_thread_t * const th, const rb_iseq_t *iseq,
+		    int orig_argc, VALUE *argv,
+		    const rb_block_t *blockptr, int lambda)
 {
     if (0) { /* for debug */
-	printf("     argc: %d\n", argc);
+	printf("     argc: %d\n", orig_argc);
 	printf("iseq argc: %d\n", iseq->argc);
 	printf("iseq opts: %d\n", iseq->arg_opts);
 	printf("iseq rest: %d\n", iseq->arg_rest);
@@ -693,10 +699,11 @@
 
     if (lambda) {
 	/* call as method */
-	return vm_callee_setup_arg(th, iseq, argc, argv, &blockptr);
+	return vm_callee_setup_arg(th, iseq, orig_argc, argv, &blockptr);
     }
     else {
 	int i;
+	int argc = orig_argc;
 	const int m = iseq->argc;
 
 	th->mark_stack_len = argc;
@@ -796,8 +803,7 @@
 static VALUE
 vm_invoke_block(rb_thread_t *th, rb_control_frame_t *reg_cfp, rb_num_t num, rb_num_t flag)
 {
-    VALUE val;
-    rb_block_t *block = GET_BLOCK_PTR();
+    rb_block_t * const block = GET_BLOCK_PTR();
     rb_iseq_t *iseq;
     int argc = num;
 
@@ -811,7 +817,7 @@
     if (BUILTIN_TYPE(iseq) != T_NODE) {
 	int opt_pc;
 	const int arg_size = iseq->arg_size;
-	VALUE *rsp = GET_SP() - argc;
+	VALUE * const rsp = GET_SP() - argc;
 	SET_SP(rsp);
 
 	CHECK_STACK_OVERFLOW(GET_CFP(), iseq->stack_max);
@@ -826,51 +832,30 @@
 	return Qundef;
     }
     else {
-	val = vm_yield_with_cfunc(th, block, block->self, argc, STACK_ADDR_FROM_TOP(argc));
+	VALUE val = vm_yield_with_cfunc(th, block, block->self, argc, STACK_ADDR_FROM_TOP(argc));
 	POPN(argc); /* TODO: should put before C/yield? */
 	return val;
     }
 }
 
-/* cref */
+/* svar */
 
-static NODE *
-lfp_get_special_cref(VALUE *lfp)
-{
-    struct RValues *values;
-    if (((VALUE)(values = (void *)lfp[-1])) != Qnil && values->basic.klass) {
-	return (NODE *)values->basic.klass;
-    }
-    else {
-	return 0;
-    }
-}
-
-static struct RValues *
-new_value(void)
-{
-    NEWOBJ(val, struct RValues);
-    OBJSETUP(val, 0, T_VALUES);
-    val->v1 = val->v2 = val->v3 = Qnil;
-    return val;
-}
-
-static struct RValues *
+static inline NODE *
 lfp_svar_place(rb_thread_t *th, VALUE *lfp)
 {
-    struct RValues *svar;
+    NODE *svar;
 
     if (th->local_lfp != lfp) {
-	svar = (struct RValues *)lfp[-1];
+	svar = (NODE *)lfp[-1];
 	if ((VALUE)svar == Qnil) {
-	    svar = new_value();
+	    svar = NEW_IF(Qnil, Qnil, Qnil);
 	    GC_WB(&lfp[-1], svar);
 	}
     }
     else {
-	svar = (struct RValues *)th->local_svar;
+	svar = (NODE *)th->local_svar;
 	if ((VALUE)svar == Qnil) {
-	    svar = new_value();
+	    svar = NEW_IF(Qnil, Qnil, Qnil);
 	    GC_WB(&th->local_svar, (VALUE)svar);
 	}
     }
@@ -880,17 +865,15 @@
 static VALUE
 lfp_svar_get(rb_thread_t *th, VALUE *lfp, VALUE key)
 {
-    struct RValues *svar = lfp_svar_place(th, lfp);
+    NODE *svar = lfp_svar_place(th, lfp);
 
     switch (key) {
       case 0:
-	return svar->v1;
+	return svar->u1.value;
       case 1:
-	return svar->v2;
-      case 2:
-	return svar->basic.klass;
+	return svar->u2.value;
       default: {
-	VALUE hash = svar->v3;
+	const VALUE hash = svar->u3.value;
 
 	if (hash == Qnil) {
 	    return Qnil;
@@ -905,54 +888,38 @@
 static void
 lfp_svar_set(rb_thread_t *th, VALUE *lfp, VALUE key, VALUE val)
 {
-    struct RValues *svar = lfp_svar_place(th, lfp);
+    NODE *svar = lfp_svar_place(th, lfp);
 
     switch (key) {
       case 0:
-	GC_WB(&svar->v1, val);
+	GC_WB(&svar->u1.value, val);
 	return;
       case 1:
-	GC_WB(&svar->v2, val);
+	GC_WB(&svar->u2.value, val);
 	return;
-      case 2:
-	GC_WB(&svar->basic.klass, val);
-	return;
       default: {
-	VALUE hash = svar->v3;
+	VALUE hash = svar->u3.value;
 
 	if (hash == Qnil) {
-	    svar->v3 = hash = rb_hash_new();
-	    GC_WB(&svar->v3, hash);
+	    svar->u3.value = hash = rb_hash_new();
+	    GC_WB(&svar->u3.value, hash);
 	}
 	rb_hash_aset(hash, key, val);
       }
     }
 }
 
-static NODE *
-get_cref(rb_iseq_t *iseq, VALUE *lfp)
-{
-    NODE *cref;
-    if ((cref = lfp_get_special_cref(lfp)) != 0) {
-	/* */
-    }
-    else if ((cref = iseq->cref_stack) != 0) {
-	/* */
-    }
-    else {
-	rb_bug("get_cref: unreachable");
-    }
-    return cref;
-}
-
 static inline VALUE
 vm_getspecial(rb_thread_t *th, VALUE *lfp, VALUE key, rb_num_t type)
 {
     VALUE val;
 
     if (type == 0) {
-	if (FIXNUM_P(key)) key = FIX2INT(key);
-	val = lfp_svar_get(th, lfp, key);
+	VALUE k = key;
+	if (FIXNUM_P(key)) {
+	    k = FIX2INT(key);
+	}
+	val = lfp_svar_get(th, lfp, k);
     }
     else {
 	VALUE backref = lfp_svar_get(th, lfp, 1);
@@ -982,6 +949,30 @@
     return val;
 }
 
+static NODE *
+vm_get_cref(const rb_iseq_t *iseq, const VALUE *lfp, const VALUE *dfp)
+{
+    NODE *cref = 0;
+
+    while (1) {
+	if (lfp == dfp) {
+	    cref = iseq->cref_stack;
+	    break;
+	}
+	else if (dfp[-1] != Qnil) {
+	    cref = (NODE *)dfp[-1];
+	    break;
+	}
+	dfp = GET_PREV_DFP(dfp);
+    }
+
+    if (cref == 0) {
+	rb_bug("vm_get_cref: unreachable");
+    }
+    return cref;
+}
+
+
 static inline void
 vm_check_if_namespace(VALUE klass)
 {
@@ -996,51 +987,47 @@
 }
 
 static inline VALUE
-vm_get_ev_const(rb_thread_t *th, rb_iseq_t *iseq,
-		VALUE klass, ID id, int is_defined)
+vm_get_ev_const(rb_thread_t *th, const rb_iseq_t *iseq,
+		VALUE orig_klass, ID id, int is_defined)
 {
     VALUE val;
 
-    if (klass == Qnil) {
+    if (orig_klass == Qnil) {
 	/* in current lexical scope */
-	NODE *root_cref = get_cref(iseq, th->cfp->lfp);
-	NODE *cref = root_cref;
+	const NODE *root_cref = vm_get_cref(iseq, th->cfp->lfp, th->cfp->dfp);
+	const NODE *cref = root_cref;
+	VALUE klass = orig_klass;
 
 	while (cref && cref->nd_next) {
 	    klass = cref->nd_clss;
 	    cref = cref->nd_next;
 
-	    if (klass == 0) {
-		continue;
-	    }
-	    if (NIL_P(klass)) {
-		if (is_defined) {
-		    /* TODO: check */
-		    return 1;
-		}
-		else {
-		    klass = CLASS_OF(th->cfp->self);
-		    return rb_const_get(klass, id);
-		}
-	    }
-	  search_continue:
-	    if (RCLASS_IV_TBL(klass) &&
-		st_lookup(RCLASS_IV_TBL(klass), id, &val)) {
-		if (val == Qundef) {
-		    rb_autoload_load(klass, id);
-		    goto search_continue;
-		}
-		else {
-		    if (is_defined) {
-			return 1;
+	    if (!NIL_P(klass)) {
+	      search_continue:
+		if (RCLASS_IV_TBL(klass) &&
+		    st_lookup(RCLASS_IV_TBL(klass), id, &val)) {
+		    if (val == Qundef) {
+			rb_autoload_load(klass, id);
+			goto search_continue;
 		    }
 		    else {
-			return val;
+			if (is_defined) {
+			    return 1;
+			}
+			else {
+			    return val;
+			}
 		    }
 		}
 	    }
 	}
+
+	/* search self */
 	klass = root_cref->nd_clss;
+	if (NIL_P(klass)) {
+	    klass = CLASS_OF(th->cfp->self);
+	}
+
 	if (is_defined) {
 	    return rb_const_defined(klass, id);
 	}
@@ -1049,28 +1036,31 @@
 	}
     }
     else {
-	vm_check_if_namespace(klass);
+	vm_check_if_namespace(orig_klass);
 	if (is_defined) {
-	    return rb_const_defined_from(klass, id);
+	    return rb_const_defined_from(orig_klass, id);
 	}
 	else {
-	    return rb_const_get_from(klass, id);
+	    return rb_const_get_from(orig_klass, id);
 	}
     }
 }
 
 static inline VALUE
-vm_get_cvar_base(rb_thread_t *th, rb_iseq_t *iseq)
+vm_get_cvar_base(NODE *cref)
 {
-    NODE *cref = get_cref(iseq, th->cfp->lfp);
-    VALUE klass = Qnil;
+    VALUE klass;
 
-    if (cref) {
-	klass = cref->nd_clss;
+    while (cref && cref->nd_next && (NIL_P(cref->nd_clss) || FL_TEST(cref->nd_clss, FL_SINGLETON))) {
+	cref = cref->nd_next;
+
 	if (!cref->nd_next) {
 	    rb_warn("class variable access from toplevel");
 	}
     }
+
+    klass = cref->nd_clss;
+
     if (NIL_P(klass)) {
 	rb_raise(rb_eTypeError, "no class variables available");
     }
@@ -1078,13 +1068,17 @@
 }
 
 static inline void
-vm_define_method(rb_thread_t *th, VALUE obj,
-		   ID id, rb_iseq_t *miseq, rb_num_t is_singleton, NODE *cref)
+vm_define_method(rb_thread_t *th, VALUE obj, ID id, rb_iseq_t *miseq,
+		 rb_num_t is_singleton, NODE *cref)
 {
     NODE *newbody;
-    int noex = cref->nd_visi;
     VALUE klass = cref->nd_clss;
+    int noex = cref->nd_visi;
 
+    if (NIL_P(klass)) {
+	rb_raise(rb_eTypeError, "no class/module to add method");
+    }
+
     if (is_singleton) {
 	if (FIXNUM_P(obj) || SYMBOL_P(obj)) {
 	    rb_raise(rb_eTypeError,
@@ -1102,6 +1096,7 @@
 
     /* dup */
     COPY_CREF(miseq->cref_stack, cref);
+    GC_WB(&miseq->cref_stack, cref);
     miseq->klass = klass;
     miseq->defined_method_id = id;
     newbody = NEW_NODE(RUBY_VM_METHOD_NODE, 0, miseq->self, 0);
@@ -1119,72 +1114,54 @@
 			     rb_control_frame_t *cfp) 
 {
     VALUE *argv = cfp->sp - *pnum;
-    ID id;
     NODE *mn;
-    char buf[128];
+    ID id;
 
-    if (/* *pmn == NULL 
-	&&*/ *pnum == 2 
-	&& TYPE(argv[1]) == T_ARRAY 
-	&& rb_ary_is_named_args(argv[1])) {
-
-	unsigned i, count;
-
-	if ((RARRAY_LEN(argv[1]) % 2) != 0)
-	    rb_bug("invalid named arg ary len %d", RARRAY_LEN(argv[1]));
-
-	strncpy(buf, rb_id2name(*pid), sizeof buf);
-	strncat(buf, ":", sizeof buf);
-
-	count = RARRAY_LEN(argv[1]);
-
-	for (i = 0; i < count; i += 2) {
-	    VALUE sym = RARRAY_AT(argv[1], i);
-	    if (TYPE(sym) != T_SYMBOL)
-		rb_bug("expected symbol for first pair element");
-	    strncat(buf, rb_id2name(SYM2ID(sym)), sizeof buf);
-	    strncat(buf, ":", sizeof buf);
-	}
-
-	id = rb_intern(buf);
-	if ((mn = rb_method_node(CLASS_OF(recv), id)) != NULL 
-	    || (mn = rb_objc_define_objc_mid_closure(recv, id, NULL)) != NULL) {
-	    unsigned j, newnum = 1 + (count / 2);
-	    void **new_argv = alloca(sizeof(void *) * newnum);
-	    new_argv[0] = (void *)argv[0];
-	    for (i = 0, j = 1; i < count; i += 2, j++) {
-		new_argv[j] = (void *)RARRAY_AT(argv[1], i + 1);
-	    }
-	    argv = cfp->sp - newnum;
-	    cfp->bp -= newnum - *pnum;
-
-	    memcpy(argv, new_argv, sizeof(void *) * newnum);
-	    *pmn = mn;
-	    *pid = id;
-	    *pnum = newnum;
-	}
-	else {
-	    VALUE h = rb_hash_new();
-	    for (i = 0; i < count; i += 2) {
-		rb_hash_aset(h, RARRAY_AT(argv[1], i), 
-			     RARRAY_AT(argv[1], i+1));
-	    }
-	    argv[1] = h;
-	}
-	return;
-    }
-  
     if (*pmn == NULL) {
-	id = rb_objc_missing_sel(*pid, *pnum);
-	if (id != *pid) {
-	    mn = rb_objc_define_objc_mid_closure(recv, id, NULL);
+	const char *p, *mname;
+	long i;
+	mname = rb_id2name(*pid);
+	if (*pid > 1 && (p = strchr(mname, ':')) != NULL) {
+	    char buf[512];
+	    strlcpy(buf, mname, sizeof buf);
+	    buf[p - mname] = '\0';
+	    mname = p + 1;
+	    id = rb_intern(buf);
+	    mn = rb_method_node(CLASS_OF(recv), id);
 	    if (mn != NULL) {
+		VALUE h = rb_hash_new();
+		VALUE new_argv[2];
+		for (i = 1; i < *pnum; i++) {
+		    p = strchr(mname, ':');
+		    if (p == NULL)
+			return;
+		    strlcpy(buf, mname, sizeof buf);
+		    buf[p - mname] = '\0';
+		    mname = p + 1;
+		    rb_hash_aset(h, ID2SYM(rb_intern(buf)), argv[i]);
+		}
+		new_argv[0] = argv[0];
+		new_argv[1] = h;
+		memcpy(cfp->sp - 2, new_argv, sizeof(void *) * 2);
+		cfp->bp -= 2 - *pnum;
 		*pmn = mn;
 		*pid = id;
+		*pnum = 2;
 		return;
 	    }
 	}
     }
+  
+    if (*pmn == NULL) {
+	id = rb_objc_missing_sel(*pid, *pnum);
+	if (id != *pid
+	    && (mn = rb_objc_define_objc_mid_closure(recv, id, NULL)) 
+		!= NULL) {
+	    *pmn = mn;
+	    *pid = id;
+	    return;
+	}
+    }
     else {
 	mn = rb_objc_define_objc_mid_closure(recv, *pid, *pmn);
 	if (mn != NULL) {
@@ -1239,7 +1216,9 @@
 }
 
 static void
-vm_search_superclass(rb_control_frame_t *reg_cfp, rb_iseq_t *ip, VALUE recv, VALUE sigval, ID *idp, VALUE *klassp)
+vm_search_superclass(rb_control_frame_t *reg_cfp, rb_iseq_t *ip,
+		     VALUE recv, VALUE sigval,
+		     ID *idp, VALUE *klassp)
 {
     ID id;
     VALUE klass;
@@ -1285,22 +1264,18 @@
 }
 
 static VALUE
-vm_throw(rb_thread_t *th, rb_control_frame_t *reg_cfp, rb_num_t throw_state, VALUE throwobj)
+vm_throw(rb_thread_t *th, rb_control_frame_t *reg_cfp,
+	 rb_num_t throw_state, VALUE throwobj)
 {
     rb_num_t state = throw_state & 0xff;
     rb_num_t flag = throw_state & 0x8000;
     rb_num_t level = throw_state >> 16;
 
     if (state != 0) {
-	VALUE *pt;
+	VALUE *pt = 0;
 	int i;
 	if (flag != 0) {
-	    if (throw_state & 0x4000) {
-		pt = (void *)1;
-	    }
-	    else {
-		pt = 0;
-	    }
+	    pt = (void *) 1;
 	}
 	else {
 	    if (state == TAG_BREAK) {
@@ -1504,7 +1479,7 @@
 }
 
 static inline int
-check_cfunc(NODE *mn, void *func)
+check_cfunc(const NODE *mn, const void *func)
 {
     if (mn && nd_type(mn->nd_body) == NODE_CFUNC &&
 	mn->nd_body->nd_cfnc == func) {
@@ -1515,16 +1490,14 @@
     }
 }
 
-static VALUE
+static inline VALUE
 opt_eq_func(VALUE recv, VALUE obj, IC ic)
 {
     VALUE val = Qundef;
 
     if (FIXNUM_2_P(recv, obj) &&
 	BASIC_OP_UNREDEFINED_P(BOP_EQ)) {
-	long a = FIX2LONG(recv), b = FIX2LONG(obj);
-
-	if (a == b) {
+	if (recv == obj) {
 	    val = Qtrue;
 	}
 	else {

Copied: MacRuby/branches/testing/vm_method.c (from rev 248, MacRuby/trunk/vm_method.c)
===================================================================
--- MacRuby/branches/testing/vm_method.c	                        (rev 0)
+++ MacRuby/branches/testing/vm_method.c	2008-06-05 08:33:02 UTC (rev 249)
@@ -0,0 +1,1191 @@
+/* -*-c-*- */
+/*
+ * This file is included by vm_eval.c
+ */
+
+#define CACHE_SIZE 0x800
+#define CACHE_MASK 0x7ff
+#define EXPR1(c,m) ((((c)>>3)^(m))&CACHE_MASK)
+
+static void rb_vm_check_redefinition_opt_method(const NODE *node);
+
+static ID __send__, object_id;
+static ID removed, singleton_removed, undefined, singleton_undefined;
+static ID eqq, each, aref, aset, match, missing;
+static ID added, singleton_added;
+
+struct cache_entry {		/* method hash table. */
+    ID mid;			/* method's id */
+    ID mid0;			/* method's original id */
+    VALUE klass;		/* receiver's class */
+    VALUE oklass;		/* original's class */
+    NODE *method;
+};
+
+static struct cache_entry cache[CACHE_SIZE];
+#define ruby_running (GET_VM()->running)
+/* int ruby_running = 0; */
+
+void
+rb_clear_cache(void)
+{
+    struct cache_entry *ent, *end;
+
+    rb_vm_change_state();
+
+    if (!ruby_running)
+	return;
+    ent = cache;
+    end = ent + CACHE_SIZE;
+    while (ent < end) {
+	ent->mid = 0;
+	ent++;
+    }
+}
+
+static void
+rb_clear_cache_for_undef(VALUE klass, ID id)
+{
+    struct cache_entry *ent, *end;
+
+    rb_vm_change_state();
+
+    if (!ruby_running)
+	return;
+    ent = cache;
+    end = ent + CACHE_SIZE;
+    while (ent < end) {
+	if (ent->oklass == klass && ent->mid == id) {
+	    ent->mid = 0;
+	}
+	ent++;
+    }
+}
+
+static void
+rb_clear_cache_by_id(ID id)
+{
+    struct cache_entry *ent, *end;
+
+    rb_vm_change_state();
+
+    if (!ruby_running)
+	return;
+    ent = cache;
+    end = ent + CACHE_SIZE;
+    while (ent < end) {
+	if (ent->mid == id) {
+	    ent->mid = 0;
+	}
+	ent++;
+    }
+}
+
+void
+rb_clear_cache_by_class(VALUE klass)
+{
+    struct cache_entry *ent, *end;
+
+    rb_vm_change_state();
+
+    if (!ruby_running)
+	return;
+    ent = cache;
+    end = ent + CACHE_SIZE;
+    while (ent < end) {
+	if (ent->klass == klass || ent->oklass == klass) {
+	    ent->mid = 0;
+	}
+	ent++;
+    }
+}
+
+#if WITH_OBJC
+void rb_objc_sync_ruby_method(VALUE, ID, NODE*, unsigned);
+#endif
+
+void
+rb_add_method_direct(VALUE klass, ID mid, NODE *node)
+{
+    rb_clear_cache_by_id(mid);
+    st_insert(RCLASS_M_TBL(klass), (st_data_t)mid, (st_data_t)node);
+}
+
+void
+rb_add_method(VALUE klass, ID mid, NODE * node, int noex)
+{
+    NODE *body;
+
+    if (NIL_P(klass) || klass == 0) {
+	klass = rb_cObject;
+    }
+    if (rb_safe_level() >= 4 && (klass == rb_cObject || !OBJ_TAINTED(klass))) {
+	rb_raise(rb_eSecurityError, "Insecure: can't define method");
+    }
+    if (!FL_TEST(klass, FL_SINGLETON) &&
+	node && nd_type(node) != NODE_ZSUPER &&
+	(mid == rb_intern("initialize") || mid == rb_intern("initialize_copy"))) {
+	noex = NOEX_PRIVATE | noex;
+    }
+    else if (FL_TEST(klass, FL_SINGLETON) && node
+	     && nd_type(node) == NODE_CFUNC && mid == rb_intern("allocate")) {
+	rb_warn
+	    ("defining %s.allocate is deprecated; use rb_define_alloc_func()",
+	     rb_class2name(rb_iv_get(klass, "__attached__")));
+	mid = ID_ALLOCATOR;
+    }
+    if (OBJ_FROZEN(klass)) {
+	rb_error_frozen("class/module");
+    }
+    rb_clear_cache_by_id(mid);
+
+    /*
+     * NODE_METHOD (NEW_METHOD(body, klass, vis)):
+     *   nd_body : method body   // (2) // mark
+     *   nd_clss : klass         // (1) // mark
+     *   nd_noex : visibility    // (3)
+     *
+     * NODE_FBODY (NEW_FBODY(method, alias)):
+     *   nd_body : method (NODE_METHOD)  // (2) // mark
+     *   nd_oid  : original id           // (1)
+     *   nd_cnt  : alias count           // (3)
+     */
+    if (node) {
+	body = NEW_FBODY(NEW_METHOD(node, klass, NOEX_WITH_SAFE(noex)), 0);
+    }
+    else {
+	body = 0;
+    }
+
+    {
+	/* check re-definition */
+	st_data_t data;
+	NODE *old_node;
+
+	if (st_lookup(RCLASS_M_TBL(klass), mid, &data)) {
+	    old_node = (NODE *)data;
+	    if (old_node) {
+		if (nd_type(old_node->nd_body->nd_body) == NODE_CFUNC) {
+		    rb_vm_check_redefinition_opt_method(old_node);
+		}
+		if (RTEST(ruby_verbose) && node && old_node->nd_cnt == 0 && old_node->nd_body) {
+		    rb_warning("method redefined; discarding old %s", rb_id2name(mid));
+		}
+	    }
+	}
+	if (klass == rb_cObject && node && mid == idInitialize) {
+	    rb_warn("redefining Object#initialize may cause infinite loop");
+	}
+
+	if (mid == object_id || mid == __send__) {
+	    if (node && nd_type(node) == RUBY_VM_METHOD_NODE) {
+		rb_warn("redefining `%s' may cause serious problem",
+			rb_id2name(mid));
+	    }
+	}
+    }
+
+    st_insert(RCLASS_M_TBL(klass), mid, (st_data_t) body);
+
+#if WITH_OBJC
+    if (node != NULL && noex == NOEX_PUBLIC) {
+	unsigned override = !FL_TEST(klass, FL_SINGLETON);
+	rb_objc_sync_ruby_method(klass, mid, node, override);
+    }
+#endif
+
+    if (node && mid != ID_ALLOCATOR && ruby_running) {
+	if (FL_TEST(klass, FL_SINGLETON)) {
+	    rb_funcall(rb_iv_get(klass, "__attached__"), singleton_added, 1,
+		       ID2SYM(mid));
+	}
+	else {
+	    rb_funcall(klass, added, 1, ID2SYM(mid));
+	}
+    }
+}
+
+void
+rb_define_alloc_func(VALUE klass, VALUE (*func)(VALUE))
+{
+    Check_Type(klass, T_CLASS);
+    rb_add_method(rb_singleton_class(klass), ID_ALLOCATOR, NEW_CFUNC(func, 0),
+		  NOEX_PRIVATE);
+}
+
+void
+rb_undef_alloc_func(VALUE klass)
+{
+    Check_Type(klass, T_CLASS);
+    rb_add_method(rb_singleton_class(klass), ID_ALLOCATOR, 0, NOEX_UNDEF);
+}
+
+rb_alloc_func_t
+rb_get_alloc_func(VALUE klass)
+{
+    NODE *n;
+    Check_Type(klass, T_CLASS);
+    n = rb_method_node(CLASS_OF(klass), ID_ALLOCATOR);
+    if (!n) return 0;
+    if (nd_type(n) != NODE_METHOD) return 0;
+    n = n->nd_body;
+    if (nd_type(n) != NODE_CFUNC) return 0;
+    return (rb_alloc_func_t)n->nd_cfnc;
+}
+
+static NODE *
+search_method(VALUE klass, ID id, VALUE *klassp)
+{
+    st_data_t body;
+
+    if (!klass) {
+	return 0;
+    }
+
+    while (!st_lookup(RCLASS_M_TBL(klass), id, &body)) {
+	klass = RCLASS_SUPER(klass);
+	if (!klass)
+	    return 0;
+    }
+
+    if (klassp) {
+	*klassp = klass;
+    }
+
+    return (NODE *)body;
+}
+
+/*
+ * search method body (NODE_METHOD)
+ *   with    : klass and id
+ *   without : method cache
+ *
+ * if you need method node with method cache, use
+ * rb_method_node()
+ */
+NODE *
+rb_get_method_body(VALUE klass, ID id, ID *idp)
+{
+    NODE *volatile fbody, *body;
+    NODE *method;
+
+    if ((fbody = search_method(klass, id, 0)) == 0 || !fbody->nd_body) {
+	/* store empty info in cache */
+	struct cache_entry *ent;
+	ent = cache + EXPR1(klass, id);
+	ent->klass = klass;
+	ent->mid = ent->mid0 = id;
+	ent->method = 0;
+	ent->oklass = 0;
+	return 0;
+    }
+
+    method = fbody->nd_body;
+
+    if (ruby_running) {
+	/* store in cache */
+	struct cache_entry *ent;
+	ent = cache + EXPR1(klass, id);
+	ent->klass = klass;
+	ent->mid = id;
+	ent->mid0 = fbody->nd_oid;
+	ent->method = body = method;
+	ent->oklass = method->nd_clss;
+    }
+    else {
+	body = method;
+    }
+
+    if (idp) {
+	*idp = fbody->nd_oid;
+    }
+
+    return body;
+}
+
+NODE *
+rb_method_node(VALUE klass, ID id)
+{
+    struct cache_entry *ent;
+
+    ent = cache + EXPR1(klass, id);
+    if (ent->mid == id && ent->klass == klass && ent->method) {
+	return ent->method;
+    }
+
+    return rb_get_method_body(klass, id, 0);
+}
+
+static void
+remove_method(VALUE klass, ID mid)
+{
+    st_data_t data;
+    NODE *body = 0;
+
+    if (klass == rb_cObject) {
+	rb_secure(4);
+    }
+    if (rb_safe_level() >= 4 && !OBJ_TAINTED(klass)) {
+	rb_raise(rb_eSecurityError, "Insecure: can't remove method");
+    }
+    if (OBJ_FROZEN(klass))
+	rb_error_frozen("class/module");
+    if (mid == object_id || mid == __send__ || mid == idInitialize) {
+	rb_warn("removing `%s' may cause serious problem", rb_id2name(mid));
+    }
+    if (st_lookup(RCLASS_M_TBL(klass), mid, &data)) {
+	body = (NODE *)data;
+	if (!body || !body->nd_body) body = 0;
+	else {
+	    st_delete(RCLASS_M_TBL(klass), &mid, &data);
+	}
+    }
+    if (!body) {
+	rb_name_error(mid, "method `%s' not defined in %s",
+		      rb_id2name(mid), rb_class2name(klass));
+    }
+
+    if (nd_type(body->nd_body->nd_body) == NODE_CFUNC) {
+	rb_vm_check_redefinition_opt_method(body);
+    }
+
+    rb_clear_cache_for_undef(klass, mid);
+    if (FL_TEST(klass, FL_SINGLETON)) {
+	rb_funcall(rb_iv_get(klass, "__attached__"), singleton_removed, 1,
+		   ID2SYM(mid));
+    }
+    else {
+	rb_funcall(klass, removed, 1, ID2SYM(mid));
+    }
+}
+
+void
+rb_remove_method(VALUE klass, const char *name)
+{
+    remove_method(klass, rb_intern(name));
+}
+
+/*
+ *  call-seq:
+ *     remove_method(symbol)   => self
+ *
+ *  Removes the method identified by _symbol_ from the current
+ *  class. For an example, see <code>Module.undef_method</code>.
+ */
+
+static VALUE
+rb_mod_remove_method(int argc, VALUE *argv, VALUE mod)
+{
+    int i;
+
+    for (i = 0; i < argc; i++) {
+	remove_method(mod, rb_to_id(argv[i]));
+    }
+    return mod;
+}
+
+#undef rb_disable_super
+#undef rb_enable_super
+
+void
+rb_disable_super(VALUE klass, const char *name)
+{
+    /* obsolete - no use */
+}
+
+void
+rb_enable_super(VALUE klass, const char *name)
+{
+    rb_warning("rb_enable_super() is obsolete");
+}
+
+static void
+rb_export_method(VALUE klass, ID name, ID noex)
+{
+    NODE *fbody;
+    VALUE origin;
+
+    if (klass == rb_cObject) {
+	rb_secure(4);
+    }
+    fbody = search_method(klass, name, &origin);
+    if (!fbody && TYPE(klass) == T_MODULE) {
+	fbody = search_method(rb_cObject, name, &origin);
+    }
+    if (!fbody || !fbody->nd_body) {
+	rb_print_undef(klass, name, 0);
+    }
+    if (fbody->nd_body->nd_noex != noex) {
+	if (nd_type(fbody->nd_body->nd_body) == NODE_CFUNC) {
+	    rb_vm_check_redefinition_opt_method(fbody);
+	}
+	if (klass == origin) {
+	    fbody->nd_body->nd_noex = noex;
+	}
+	else {
+	    rb_add_method(klass, name, NEW_ZSUPER(), noex);
+	}
+    }
+}
+
+int
+rb_method_boundp(VALUE klass, ID id, int ex)
+{
+    NODE *method;
+
+    if ((method = rb_method_node(klass, id)) != 0) {
+	if (ex && (method->nd_noex & NOEX_PRIVATE)) {
+	    return Qfalse;
+	}
+	return Qtrue;
+    }
+    return Qfalse;
+}
+
+void
+rb_attr(VALUE klass, ID id, int read, int write, int ex)
+{
+    const char *name;
+    ID attriv;
+    int noex;
+
+    if (!ex) {
+	noex = NOEX_PUBLIC;
+    }
+    else {
+	if (SCOPE_TEST(NOEX_PRIVATE)) {
+	    noex = NOEX_PRIVATE;
+	    rb_warning((SCOPE_CHECK(NOEX_MODFUNC)) ?
+		       "attribute accessor as module_function" :
+		       "private attribute?");
+	}
+	else if (SCOPE_TEST(NOEX_PROTECTED)) {
+	    noex = NOEX_PROTECTED;
+	}
+	else {
+	    noex = NOEX_PUBLIC;
+	}
+    }
+
+    if (!rb_is_local_id(id) && !rb_is_const_id(id)) {
+	rb_name_error(id, "invalid attribute name `%s'", rb_id2name(id));
+    }
+    name = rb_id2name(id);
+    if (!name) {
+	rb_raise(rb_eArgError, "argument needs to be symbol or string");
+    }
+    attriv = rb_intern_str(rb_sprintf("@%s", name));
+    if (read) {
+	rb_add_method(klass, id, NEW_IVAR(attriv), noex);
+    }
+    if (write) {
+	rb_add_method(klass, rb_id_attrset(id), NEW_ATTRSET(attriv), noex);
+    }
+}
+
+void
+rb_undef(VALUE klass, ID id)
+{
+    VALUE origin;
+    NODE *body;
+
+    if (rb_vm_cbase() == rb_cObject && klass == rb_cObject) {
+	rb_secure(4);
+    }
+    if (rb_safe_level() >= 4 && !OBJ_TAINTED(klass)) {
+	rb_raise(rb_eSecurityError, "Insecure: can't undef `%s'",
+		 rb_id2name(id));
+    }
+    rb_frozen_class_p(klass);
+    if (id == object_id || id == __send__ || id == idInitialize) {
+	rb_warn("undefining `%s' may cause serious problem", rb_id2name(id));
+    }
+#if WITH_OBJC
+    /* TODO: we should only warn regarding important NSObject methods that
+       are necessary by the GC to call finalizers. */
+    if (class_respondsToSelector(RCLASS_OCID(rb_cBasicObject),
+				 sel_registerName(rb_id2name(id)))) {
+	rb_warn("undefining `NSObject#%s' may cause serious problem", 
+		rb_id2name(id));
+    }
+#endif
+    body = search_method(klass, id, &origin);
+    if (!body || !body->nd_body) {
+	const char *s0 = " class";
+	VALUE c = klass;
+
+	if (FL_TEST(c, FL_SINGLETON)) {
+	    VALUE obj = rb_iv_get(klass, "__attached__");
+
+	    switch (TYPE(obj)) {
+	      case T_MODULE:
+	      case T_CLASS:
+		c = obj;
+		s0 = "";
+	    }
+	}
+	else if (TYPE(c) == T_MODULE) {
+	    s0 = " module";
+	}
+#if WITH_OBJC
+	if (!class_respondsToSelector(RCLASS(klass)->ocklass,
+	    			      sel_registerName(rb_id2name(id))))
+#endif
+	rb_name_error(id, "undefined method `%s' for%s `%s'",
+		      rb_id2name(id), s0, rb_class2name(c));
+    }
+
+    rb_add_method(klass, id, 0, NOEX_PUBLIC);
+
+#if WITH_OBJC
+    {
+	Method method;
+        method = class_getInstanceMethod(RCLASS(klass)->ocklass,
+	 				 sel_registerName(rb_id2name(id)));
+	if (method != NULL)
+	    method_setImplementation(method, NULL);
+    }
+#endif
+
+    if (FL_TEST(klass, FL_SINGLETON)) {
+	rb_funcall(rb_iv_get(klass, "__attached__"),
+		   singleton_undefined, 1, ID2SYM(id));
+    }
+    else {
+	rb_funcall(klass, undefined, 1, ID2SYM(id));
+    }
+}
+
+/*
+ *  call-seq:
+ *     undef_method(symbol)    => self
+ *
+ *  Prevents the current class from responding to calls to the named
+ *  method. Contrast this with <code>remove_method</code>, which deletes
+ *  the method from the particular class; Ruby will still search
+ *  superclasses and mixed-in modules for a possible receiver.
+ *
+ *     class Parent
+ *       def hello
+ *         puts "In parent"
+ *       end
+ *     end
+ *     class Child < Parent
+ *       def hello
+ *         puts "In child"
+ *       end
+ *     end
+ *
+ *
+ *     c = Child.new
+ *     c.hello
+ *
+ *
+ *     class Child
+ *       remove_method :hello  # remove from child, still in parent
+ *     end
+ *     c.hello
+ *
+ *
+ *     class Child
+ *       undef_method :hello   # prevent any calls to 'hello'
+ *     end
+ *     c.hello
+ *
+ *  <em>produces:</em>
+ *
+ *     In child
+ *     In parent
+ *     prog.rb:23: undefined method `hello' for #<Child:0x401b3bb4> (NoMethodError)
+ */
+
+static VALUE
+rb_mod_undef_method(int argc, VALUE *argv, VALUE mod)
+{
+    int i;
+    for (i = 0; i < argc; i++) {
+	rb_undef(mod, rb_to_id(argv[i]));
+    }
+    return mod;
+}
+
+/*
+ *  call-seq:
+ *     mod.method_defined?(symbol)    => true or false
+ *
+ *  Returns +true+ if the named method is defined by
+ *  _mod_ (or its included modules and, if _mod_ is a class,
+ *  its ancestors). Public and protected methods are matched.
+ *
+ *     module A
+ *       def method1()  end
+ *     end
+ *     class B
+ *       def method2()  end
+ *     end
+ *     class C < B
+ *       include A
+ *       def method3()  end
+ *     end
+ *
+ *     A.method_defined? :method1    #=> true
+ *     C.method_defined? "method1"   #=> true
+ *     C.method_defined? "method2"   #=> true
+ *     C.method_defined? "method3"   #=> true
+ *     C.method_defined? "method4"   #=> false
+ */
+
+static VALUE
+rb_mod_method_defined(VALUE mod, VALUE mid)
+{
+    return rb_method_boundp(mod, rb_to_id(mid), 1);
+}
+
+#define VISI_CHECK(x,f) (((x)&NOEX_MASK) == (f))
+
+/*
+ *  call-seq:
+ *     mod.public_method_defined?(symbol)   => true or false
+ *
+ *  Returns +true+ if the named public method is defined by
+ *  _mod_ (or its included modules and, if _mod_ is a class,
+ *  its ancestors).
+ *
+ *     module A
+ *       def method1()  end
+ *     end
+ *     class B
+ *       protected
+ *       def method2()  end
+ *     end
+ *     class C < B
+ *       include A
+ *       def method3()  end
+ *     end
+ *
+ *     A.method_defined? :method1           #=> true
+ *     C.public_method_defined? "method1"   #=> true
+ *     C.public_method_defined? "method2"   #=> false
+ *     C.method_defined? "method2"          #=> true
+ */
+
+static VALUE
+rb_mod_public_method_defined(VALUE mod, VALUE mid)
+{
+    ID id = rb_to_id(mid);
+    NODE *method;
+
+    method = rb_method_node(mod, id);
+    if (method) {
+	if (VISI_CHECK(method->nd_noex, NOEX_PUBLIC))
+	    return Qtrue;
+    }
+    return Qfalse;
+}
+
+/*
+ *  call-seq:
+ *     mod.private_method_defined?(symbol)    => true or false
+ *
+ *  Returns +true+ if the named private method is defined by
+ *  _ mod_ (or its included modules and, if _mod_ is a class,
+ *  its ancestors).
+ *
+ *     module A
+ *       def method1()  end
+ *     end
+ *     class B
+ *       private
+ *       def method2()  end
+ *     end
+ *     class C < B
+ *       include A
+ *       def method3()  end
+ *     end
+ *
+ *     A.method_defined? :method1            #=> true
+ *     C.private_method_defined? "method1"   #=> false
+ *     C.private_method_defined? "method2"   #=> true
+ *     C.method_defined? "method2"           #=> false
+ */
+
+static VALUE
+rb_mod_private_method_defined(VALUE mod, VALUE mid)
+{
+    ID id = rb_to_id(mid);
+    NODE *method;
+
+    method = rb_method_node(mod, id);
+    if (method) {
+	if (VISI_CHECK(method->nd_noex, NOEX_PRIVATE))
+	    return Qtrue;
+    }
+    return Qfalse;
+}
+
+/*
+ *  call-seq:
+ *     mod.protected_method_defined?(symbol)   => true or false
+ *
+ *  Returns +true+ if the named protected method is defined
+ *  by _mod_ (or its included modules and, if _mod_ is a
+ *  class, its ancestors).
+ *
+ *     module A
+ *       def method1()  end
+ *     end
+ *     class B
+ *       protected
+ *       def method2()  end
+ *     end
+ *     class C < B
+ *       include A
+ *       def method3()  end
+ *     end
+ *
+ *     A.method_defined? :method1              #=> true
+ *     C.protected_method_defined? "method1"   #=> false
+ *     C.protected_method_defined? "method2"   #=> true
+ *     C.method_defined? "method2"             #=> true
+ */
+
+static VALUE
+rb_mod_protected_method_defined(VALUE mod, VALUE mid)
+{
+    ID id = rb_to_id(mid);
+    NODE *method;
+
+    method = rb_method_node(mod, id);
+    if (method) {
+	if (VISI_CHECK(method->nd_noex, NOEX_PROTECTED))
+	    return Qtrue;
+    }
+    return Qfalse;
+}
+
+void
+rb_alias(VALUE klass, ID name, ID def)
+{
+    NODE *orig_fbody, *node;
+    VALUE singleton = 0;
+    st_data_t data;
+
+    rb_frozen_class_p(klass);
+    if (klass == rb_cObject) {
+	rb_secure(4);
+    }
+    orig_fbody = search_method(klass, def, 0);
+    if (!orig_fbody || !orig_fbody->nd_body) {
+	if (TYPE(klass) == T_MODULE) {
+	    orig_fbody = search_method(rb_cObject, def, 0);
+	}
+    }
+    if (!orig_fbody || !orig_fbody->nd_body) {
+	rb_print_undef(klass, def, 0);
+    }
+    if (FL_TEST(klass, FL_SINGLETON)) {
+	singleton = rb_iv_get(klass, "__attached__");
+    }
+
+    orig_fbody->nd_cnt++;
+
+    if (st_lookup(RCLASS_M_TBL(klass), name, &data)) {
+	node = (NODE *)data;
+	if (node) {
+	    if (RTEST(ruby_verbose) && node->nd_cnt == 0 && node->nd_body) {
+		rb_warning("discarding old %s", rb_id2name(name));
+	    }
+	    if (nd_type(node->nd_body->nd_body) == NODE_CFUNC) {
+		rb_vm_check_redefinition_opt_method(node);
+	    }
+	}
+    }
+
+    st_insert(RCLASS_M_TBL(klass), name,
+	      (st_data_t) NEW_FBODY(
+		  NEW_METHOD(orig_fbody->nd_body->nd_body,
+			     orig_fbody->nd_body->nd_clss,
+			     NOEX_WITH_SAFE(orig_fbody->nd_body->nd_noex)), def));
+
+#if WITH_OBJC
+    if (orig_fbody->nd_body->nd_noex == NOEX_PUBLIC)
+	rb_objc_sync_ruby_method(klass, name, orig_fbody->nd_body->nd_body, 0);
+#endif
+
+    rb_clear_cache_by_id(name);
+
+    if (!ruby_running) return;
+
+    if (singleton) {
+	rb_funcall(singleton, singleton_added, 1, ID2SYM(name));
+    }
+    else {
+	rb_funcall(klass, added, 1, ID2SYM(name));
+    }
+}
+
+/*
+ *  call-seq:
+ *     alias_method(new_name, old_name)   => self
+ *
+ *  Makes <i>new_name</i> a new copy of the method <i>old_name</i>. This can
+ *  be used to retain access to methods that are overridden.
+ *
+ *     module Mod
+ *       alias_method :orig_exit, :exit
+ *       def exit(code=0)
+ *         puts "Exiting with code #{code}"
+ *         orig_exit(code)
+ *       end
+ *     end
+ *     include Mod
+ *     exit(99)
+ *
+ *  <em>produces:</em>
+ *
+ *     Exiting with code 99
+ */
+
+static VALUE
+rb_mod_alias_method(VALUE mod, VALUE newname, VALUE oldname)
+{
+    rb_alias(mod, rb_to_id(newname), rb_to_id(oldname));
+    return mod;
+}
+
+static void
+secure_visibility(VALUE self)
+{
+    if (rb_safe_level() >= 4 && !OBJ_TAINTED(self)) {
+	rb_raise(rb_eSecurityError,
+		 "Insecure: can't change method visibility");
+    }
+}
+
+static void
+set_method_visibility(VALUE self, int argc, VALUE *argv, ID ex)
+{
+    int i;
+    secure_visibility(self);
+    for (i = 0; i < argc; i++) {
+	rb_export_method(self, rb_to_id(argv[i]), ex);
+    }
+    rb_clear_cache_by_class(self);
+}
+
+/*
+ *  call-seq:
+ *     public                 => self
+ *     public(symbol, ...)    => self
+ *
+ *  With no arguments, sets the default visibility for subsequently
+ *  defined methods to public. With arguments, sets the named methods to
+ *  have public visibility.
+ */
+
+static VALUE
+rb_mod_public(int argc, VALUE *argv, VALUE module)
+{
+    secure_visibility(module);
+    if (argc == 0) {
+	SCOPE_SET(NOEX_PUBLIC);
+    }
+    else {
+	set_method_visibility(module, argc, argv, NOEX_PUBLIC);
+    }
+    return module;
+}
+
+/*
+ *  call-seq:
+ *     protected                => self
+ *     protected(symbol, ...)   => self
+ *
+ *  With no arguments, sets the default visibility for subsequently
+ *  defined methods to protected. With arguments, sets the named methods
+ *  to have protected visibility.
+ */
+
+static VALUE
+rb_mod_protected(int argc, VALUE *argv, VALUE module)
+{
+    secure_visibility(module);
+    if (argc == 0) {
+	SCOPE_SET(NOEX_PROTECTED);
+    }
+    else {
+	set_method_visibility(module, argc, argv, NOEX_PROTECTED);
+    }
+    return module;
+}
+
+/*
+ *  call-seq:
+ *     private                 => self
+ *     private(symbol, ...)    => self
+ *
+ *  With no arguments, sets the default visibility for subsequently
+ *  defined methods to private. With arguments, sets the named methods
+ *  to have private visibility.
+ *
+ *     module Mod
+ *       def a()  end
+ *       def b()  end
+ *       private
+ *       def c()  end
+ *       private :a
+ *     end
+ *     Mod.private_instance_methods   #=> [:a, :c]
+ */
+
+static VALUE
+rb_mod_private(int argc, VALUE *argv, VALUE module)
+{
+    secure_visibility(module);
+    if (argc == 0) {
+	SCOPE_SET(NOEX_PRIVATE);
+    }
+    else {
+	set_method_visibility(module, argc, argv, NOEX_PRIVATE);
+    }
+    return module;
+}
+
+/*
+ *  call-seq:
+ *     mod.public_class_method(symbol, ...)    => mod
+ *
+ *  Makes a list of existing class methods public.
+ */
+
+static VALUE
+rb_mod_public_method(int argc, VALUE *argv, VALUE obj)
+{
+    set_method_visibility(CLASS_OF(obj), argc, argv, NOEX_PUBLIC);
+    return obj;
+}
+
+/*
+ *  call-seq:
+ *     mod.private_class_method(symbol, ...)   => mod
+ *
+ *  Makes existing class methods private. Often used to hide the default
+ *  constructor <code>new</code>.
+ *
+ *     class SimpleSingleton  # Not thread safe
+ *       private_class_method :new
+ *       def SimpleSingleton.create(*args, &block)
+ *         @me = new(*args, &block) if ! @me
+ *         @me
+ *       end
+ *     end
+ */
+
+static VALUE
+rb_mod_private_method(int argc, VALUE *argv, VALUE obj)
+{
+    set_method_visibility(CLASS_OF(obj), argc, argv, NOEX_PRIVATE);
+    return obj;
+}
+
+/*
+ *  call-seq:
+ *     public
+ *     public(symbol, ...)
+ *
+ *  With no arguments, sets the default visibility for subsequently
+ *  defined methods to public. With arguments, sets the named methods to
+ *  have public visibility.
+ */
+
+static VALUE
+top_public(int argc, VALUE *argv)
+{
+    return rb_mod_public(argc, argv, rb_cObject);
+}
+
+static VALUE
+top_private(int argc, VALUE *argv)
+{
+    return rb_mod_private(argc, argv, rb_cObject);
+}
+
+/*
+ *  call-seq:
+ *     module_function(symbol, ...)    => self
+ *
+ *  Creates module functions for the named methods. These functions may
+ *  be called with the module as a receiver, and also become available
+ *  as instance methods to classes that mix in the module. Module
+ *  functions are copies of the original, and so may be changed
+ *  independently. The instance-method versions are made private. If
+ *  used with no arguments, subsequently defined methods become module
+ *  functions.
+ *
+ *     module Mod
+ *       def one
+ *         "This is one"
+ *       end
+ *       module_function :one
+ *     end
+ *     class Cls
+ *       include Mod
+ *       def callOne
+ *         one
+ *       end
+ *     end
+ *     Mod.one     #=> "This is one"
+ *     c = Cls.new
+ *     c.callOne   #=> "This is one"
+ *     module Mod
+ *       def one
+ *         "This is the new one"
+ *       end
+ *     end
+ *     Mod.one     #=> "This is one"
+ *     c.callOne   #=> "This is the new one"
+ */
+
+static VALUE
+rb_mod_modfunc(int argc, VALUE *argv, VALUE module)
+{
+    int i;
+    ID id;
+    NODE *fbody;
+
+    if (TYPE(module) != T_MODULE) {
+	rb_raise(rb_eTypeError, "module_function must be called for modules");
+    }
+
+    secure_visibility(module);
+    if (argc == 0) {
+	SCOPE_SET(NOEX_MODFUNC);
+	return module;
+    }
+
+    set_method_visibility(module, argc, argv, NOEX_PRIVATE);
+
+    for (i = 0; i < argc; i++) {
+	VALUE m = module;
+
+	id = rb_to_id(argv[i]);
+	for (;;) {
+	    fbody = search_method(m, id, &m);
+	    if (fbody == 0) {
+		fbody = search_method(rb_cObject, id, &m);
+	    }
+	    if (fbody == 0 || fbody->nd_body == 0) {
+		rb_bug("undefined method `%s'; can't happen", rb_id2name(id));
+	    }
+	    if (nd_type(fbody->nd_body->nd_body) != NODE_ZSUPER) {
+		break;		/* normal case: need not to follow 'super' link */
+	    }
+	    m = RCLASS_SUPER(m);
+	    if (!m)
+		break;
+	}
+	rb_add_method(rb_singleton_class(module), id, fbody->nd_body->nd_body,
+		      NOEX_PUBLIC);
+    }
+    return module;
+}
+
+/*
+ *  call-seq:
+ *     obj.respond_to?(symbol, include_private=false) => true or false
+ *
+ *  Returns +true+> if _obj_ responds to the given
+ *  method. Private methods are included in the search only if the
+ *  optional second parameter evaluates to +true+.
+ */
+
+static NODE *basic_respond_to = 0;
+
+int
+rb_obj_respond_to(VALUE obj, ID id, int priv)
+{
+    VALUE klass = CLASS_OF(obj);
+
+    if (rb_method_node(klass, idRespond_to) == basic_respond_to) {
+	return rb_method_boundp(klass, id, !priv);
+    }
+    else {
+	VALUE args[2];
+	int n = 0;
+	args[n++] = ID2SYM(id);
+	if (priv)
+	    args[n++] = Qtrue;
+	return RTEST(rb_funcall2(obj, idRespond_to, n, args));
+    }
+}
+
+int
+rb_respond_to(VALUE obj, ID id)
+{
+    return rb_obj_respond_to(obj, id, Qfalse);
+}
+
+/*
+ *  call-seq:
+ *     obj.respond_to?(symbol, include_private=false) => true or false
+ *
+ *  Returns +true+> if _obj_ responds to the given
+ *  method. Private methods are included in the search only if the
+ *  optional second parameter evaluates to +true+.
+ */
+
+static VALUE
+obj_respond_to(int argc, VALUE *argv, VALUE obj)
+{
+    VALUE mid, priv;
+    ID id;
+
+    rb_scan_args(argc, argv, "11", &mid, &priv);
+    id = rb_to_id(mid);
+    if (rb_method_boundp(CLASS_OF(obj), id, !RTEST(priv))) {
+	return Qtrue;
+    }
+    return Qfalse;
+}
+
+void
+Init_eval_method(void)
+{
+    rb_define_method(rb_mKernel, "respond_to?", obj_respond_to, -1);
+    basic_respond_to = rb_method_node(rb_cObject, idRespond_to);
+    rb_register_mark_object((VALUE)basic_respond_to);
+
+    rb_define_private_method(rb_cModule, "remove_method", rb_mod_remove_method, -1);
+    rb_define_private_method(rb_cModule, "undef_method", rb_mod_undef_method, -1);
+    rb_define_private_method(rb_cModule, "alias_method", rb_mod_alias_method, 2);
+    rb_define_private_method(rb_cModule, "public", rb_mod_public, -1);
+    rb_define_private_method(rb_cModule, "protected", rb_mod_protected, -1);
+    rb_define_private_method(rb_cModule, "private", rb_mod_private, -1);
+    rb_define_private_method(rb_cModule, "module_function", rb_mod_modfunc, -1);
+
+    rb_define_method(rb_cModule, "method_defined?", rb_mod_method_defined, 1);
+    rb_define_method(rb_cModule, "public_method_defined?", rb_mod_public_method_defined, 1);
+    rb_define_method(rb_cModule, "private_method_defined?", rb_mod_private_method_defined, 1);
+    rb_define_method(rb_cModule, "protected_method_defined?", rb_mod_protected_method_defined, 1);
+    rb_define_method(rb_cModule, "public_class_method", rb_mod_public_method, -1);
+    rb_define_method(rb_cModule, "private_class_method", rb_mod_private_method, -1);
+
+    rb_define_singleton_method(rb_vm_top_self(), "public", top_public, -1);
+    rb_define_singleton_method(rb_vm_top_self(), "private", top_private, -1);
+
+    object_id = rb_intern("object_id");
+    __send__ = rb_intern("__send__");
+    eqq = rb_intern("===");
+    each = rb_intern("each");
+    aref = rb_intern("[]");
+    aset = rb_intern("[]=");
+    match = rb_intern("=~");
+    missing = rb_intern("method_missing");
+    added = rb_intern("method_added");
+    singleton_added = rb_intern("singleton_method_added");
+    removed = rb_intern("method_removed");
+    singleton_removed = rb_intern("singleton_method_removed");
+    undefined = rb_intern("method_undefined");
+    singleton_undefined = rb_intern("singleton_method_undefined");
+}
+

Modified: MacRuby/branches/testing/vm_opts.h
===================================================================
--- MacRuby/branches/testing/vm_opts.h	2008-06-05 08:16:41 UTC (rev 248)
+++ MacRuby/branches/testing/vm_opts.h	2008-06-05 08:33:02 UTC (rev 249)
@@ -3,7 +3,7 @@
 
   vm_opts.h - VM optimize option
 
-  $Author: nobu $
+  $Author: ko1 $
 
   Copyright (C) 2004-2007 Koichi Sasada
 
@@ -31,6 +31,7 @@
 
 /* C compiler depend */
 #define OPT_DIRECT_THREADED_CODE     1
+#define OPT_TOKEN_THREADED_CODE      0
 #define OPT_CALL_THREADED_CODE       0
 
 /* VM running option */

-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.macosforge.org/pipermail/macruby-changes/attachments/20080605/1411236c/attachment-0001.htm 


More information about the macruby-changes mailing list