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

ruby-changes:6462

From: nobu <ko1@a...>
Date: Wed, 9 Jul 2008 23:08:10 +0900 (JST)
Subject: [ruby-changes:6462] Ruby:r17978 (mvm): * merged from trunk r17917:17977.

nobu	2008-07-09 23:07:38 +0900 (Wed, 09 Jul 2008)

  New Revision: 17978

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

  Log:
    * merged from trunk r17917:17977.

  Modified files:
    branches/mvm/.merged-trunk-revision
    branches/mvm/ChangeLog
    branches/mvm/array.c
    branches/mvm/compile.h
    branches/mvm/configure.in
    branches/mvm/dir.c
    branches/mvm/ext/coverage/coverage.c
    branches/mvm/ext/nkf/nkf-utf8/nkf.c
    branches/mvm/ext/win32ole/win32ole.c
    branches/mvm/include/ruby/ruby.h
    branches/mvm/iseq.c
    branches/mvm/lib/debug.rb
    branches/mvm/lib/profile.rb
    branches/mvm/lib/profiler.rb
    branches/mvm/lib/rdoc/parsers/parse_c.rb
    branches/mvm/parse.y
    branches/mvm/string.c
    branches/mvm/test/ruby/test_dir.rb
    branches/mvm/test/ruby/test_string.rb
    branches/mvm/test/win32ole/test_win32ole_event.rb
    branches/mvm/test/win32ole/test_win32ole_type.rb
    branches/mvm/thread.c
    branches/mvm/thread_pthread.c
    branches/mvm/thread_win32.c
    branches/mvm/version.h
    branches/mvm/vm.c

Index: mvm/array.c
===================================================================
--- mvm/array.c	(revision 17977)
+++ mvm/array.c	(revision 17978)
@@ -2139,10 +2139,12 @@
 	    if (beg < 0) beg = 0;
 	}
 	len = NIL_P(arg2) ? RARRAY_LEN(ary) - beg : NUM2LONG(arg2);
-	if (len < 0) rb_raise(rb_eIndexError, "negative length (%ld)", len);
 	break;
     }
     rb_ary_modify(ary);
+    if (len < 0) {
+        return ary;
+    }
     if (beg >= ARY_MAX_SIZE || len > ARY_MAX_SIZE - beg) {
 	rb_raise(rb_eArgError, "argument too big");
     }
Index: mvm/thread_win32.c
===================================================================
--- mvm/thread_win32.c	(revision 17977)
+++ mvm/thread_win32.c	(revision 17978)
@@ -576,7 +576,8 @@
 rb_thread_create_timer_thread(void)
 {
     if (timer_thread_id == 0) {
-	timer_thread_id = w32_create_thread(1024, timer_thread_func, GET_VM());
+	timer_thread_id = w32_create_thread(1024 + (THREAD_DEBUG ? BUFSIZ : 0),
+					    timer_thread_func, GET_VM());
 	w32_resume_thread(timer_thread_id);
     }
 }
Index: mvm/include/ruby/ruby.h
===================================================================
--- mvm/include/ruby/ruby.h	(revision 17977)
+++ mvm/include/ruby/ruby.h	(revision 17978)
@@ -725,10 +725,9 @@
 
 void rb_obj_infect(VALUE,VALUE);
 
-typedef int ruby_glob_func(const char*,VALUE);
-void rb_glob(const char*,void(*)(const char*,VALUE),VALUE);
+typedef int ruby_glob_func(const char*,VALUE, void*);
+void rb_glob(const char*,void(*)(const char*,VALUE,void*),VALUE);
 int ruby_glob(const char*,int,ruby_glob_func*,VALUE);
-int ruby_brace_expand(const char*,int,ruby_glob_func*,VALUE);
 int ruby_brace_glob(const char*,int,ruby_glob_func*,VALUE);
 
 VALUE rb_define_class(const char*,VALUE);
Index: mvm/configure.in
===================================================================
--- mvm/configure.in	(revision 17977)
+++ mvm/configure.in	(revision 17978)
@@ -395,6 +395,15 @@
   AC_DEFINE(HAVE_STDARG_PROTOTYPES)
 fi
 
+AC_CACHE_CHECK(for variable length macro, rb_cv_va_args_macro,
+  [AC_TRY_COMPILE([@%:@define FOO(a, ...) foo(a, @%:@@%:@__VA_ARGS__)],
+  [FOO(1);FOO(1,2);FOO(1,2,3);],
+  rb_cv_va_args_macro=yes,
+  rb_cv_va_args_macro=no)])
+if test "$rb_cv_va_args_macro" = yes; then
+  AC_DEFINE(HAVE_VA_ARGS_MACRO)
+fi
+
 AC_DEFUN([RUBY_FUNC_ATTRIBUTE], [dnl
 m4_ifval([$2], dnl
   [AS_VAR_PUSHDEF([attrib],[$2])], dnl
Index: mvm/ChangeLog
===================================================================
--- mvm/ChangeLog	(revision 17977)
+++ mvm/ChangeLog	(revision 17978)
@@ -1,3 +1,142 @@
+Wed Jul  9 22:41:16 2008  Nobuyoshi Nakada  <nobu@r...>
+
+	* thread.c (sleep_timeval): wait until timed out.  [ruby-core:17270]
+
+Wed Jul  9 20:58:16 2008  Tanaka Akira  <akr@f...>
+
+	* array.c (rb_ary_fill): don't raise even if length is negative.
+	  [ruby-core:17483], [ruby-core:17661]
+
+Wed Jul  9 20:18:50 2008  Nobuyoshi Nakada  <nobu@r...>
+
+	* configure.in (rb_cv_va_args_macro): check for __VA_ARGS__.
+
+	* thread.c (thread_debug): show source name and line if possible.
+
+	* thread_{pthread,win32}.c (rb_thread_create_timer_thread): needs more
+	  stack for debug.
+
+Wed Jul  9 11:13:39 2008  Nobuyoshi Nakada  <nobu@r...>
+
+	* lib/profiler.rb (Profiler__#print_profile): sort in the descending
+	  order of cumulative time.
+
+Wed Jul  9 11:11:18 2008  Nobuyoshi Nakada  <nobu@r...>
+
+	* dir.c (struct glob_args, rb_glob_caller, rb_glob2, push_pattern),
+	  (glob_brace): make consistent prototypes.
+
+	* dir.c (push_glob): set enc in the caller of rb_glob_caller as well
+	  as rb_glob2.
+
+Wed Jul  9 09:12:11 2008  NARUSE, Yui  <naruse@r...>
+
+	* ext/nkf/nkf-utf8/nkf.c (options): use input_endian.
+
+Wed Jul  9 01:38:37 2008  Nobuyoshi Nakada  <nobu@r...>
+
+	* string.c (rb_str_succ): alphabets or numerics mutually enclosing
+	  non-alphanumeric characters can carry up.  e.g., "1.999".succ should
+	  be "2.000".
+
+Wed Jul  9 00:12:31 2008  Yusuke Endoh  <mame@t...>
+
+	* thread.c (rb_set_coverages, rb_reset_coverages): enable and disable
+	  coverage measurement.
+
+	* thread.c (rb_get_coverages): rename and move from vm.c.
+
+	* vm.c (rb_vm_get_coverages): ditto.
+
+	* iseq.c (prepare_iseq_build): ditto.
+
+	* thread.c (clear_coverage): ditto.
+
+	* parse.y (coverage): ditto.
+
+	* ext/coverage/coverage.c: use above functions, add new method
+	  Coverage.start and fix rdoc .
+
+Tue Jul  8 23:02:35 2008  Masaki Suketa  <masaki.suketa@n...>
+
+	* ext/win32ole/win32ole.c (find_default_source): bug fix when
+	  OLE object does not have default source interface.
+
+	* test/win32ole/test_win32ole_event.rb: ditto.
+
+Tue Jul  8 22:56:23 2008  Yusuke Endoh  <mame@t...>
+
+	* thread.c (rb_enable_coverages): hide coverage array by setting 0 to
+	  klass during measurement.
+
+	* parse.y (coverage, yycompile0): ditto.
+
+	* iseq.c (prepare_iseq_build): use rb_hash_lookup instead of
+	  rb_hash_aref.
+
+	* thread.c (rb_coverage_result): restore klass of coverage array
+	  and return it.
+
+	* theaad.c (update_coverage): chcek whether its klass is 0.
+
+Tue Jul  8 22:28:25 2008  Koichi Sasada  <ko1@a...>
+
+	* lib/debug.rb, lib/profile.rb: fix to use RubyVM.
+
+	* lib/rdoc/parsers/parse_c.rb: ditto.
+
+Tue Jul  8 21:45:22 2008  Yusuke Endoh  <mame@t...>
+
+	* vm.c (rb_vm_mark): mark the last element of special_exceptions.
+
+Tue Jul  8 19:55:40 2008  Masaki Suketa  <masaki.suketa@n...>
+
+	* ext/win32ole/win32ole.c (find_default_source): try to
+	  find COCLASS when WIN32OLE object is not COCLASS. 
+
+	* test/win32ole/test_win32ole_event.rb: ditto
+
+Tue Jul  8 13:38:22 2008  Koichi Sasada  <ko1@a...>
+
+	* compile.h: fix to skip inserting a trace insn.
+
+Tue Jul  8 11:41:17 2008  NAKAMURA Usaku  <usa@r...>
+
+	* dir.c: shoudn't use ruby object in globbing, because glob service
+	  routines are called before initializing ruby on some platforms (ex.
+	  windows).
+
+Tue Jul  8 10:08:40 2008  NARUSE, Yui  <naruse@r...>
+
+	* dir.c (Next): use rb_enc_mbclen. [ruby-dev:35390]
+
+Tue Jul  8 07:59:40 2008  NARUSE, Yui  <naruse@r...>
+
+	* dir.c (Next): use rb_enc_precise_mbclen.
+
+Tue Jul  8 02:27:23 2008  NARUSE, Yui  <naruse@r...>
+
+	* dir.c: preserve encoding of strings in glob and fnmatch.
+
+	* include/ruby/ruby.h: related changes.
+
+Tue Jul  8 00:22:58 2008  Nobuyoshi Nakada  <nobu@r...>
+
+	* string.c (rb_str_succ): limit carrying in an alphanumeric region if
+	  exists.  [ruby-dev:35094]
+
+Mon Jul  7 20:39:28 2008  Masaki Suketa  <masaki.suketa@n...>
+
+	* ext/win32ole/win32ole.c(Init_win32ole): add
+	  WIN32OLE_TYPE#source_ole_types, WIN32OLE_TYPE#default_ole_types,
+	  WIN32OLE_TYPE#default_event_sources.
+
+	* test/win32ole/test_win32ole_type.rb: ditto.
+
+Mon Jul  7 19:45:22 2008  NARUSE, Yui  <naruse@r...>
+
+	* test/ruby/test_dir.rb (test_chroot_nodir): add Errno::EPERM.
+
 Mon Jul  7 17:12:20 2008  Nobuyoshi Nakada  <nobu@r...>
 
 	* lib/ipaddr.rb (IPAddr#initialize): get rid of ArgumentError in
@@ -54,7 +193,7 @@
 Sun Jul  6 10:12:21 2008  Kouhei Sutou  <kou@c...>
 
 	* lib/test/unit/collector/objectspace.rb
-	(Test::Unit::Collector::ObjectSpace::NAME): fix a typo.
+	  (Test::Unit::Collector::ObjectSpace::NAME): fix a typo.
 
 Sun Jul  6 00:56:51 2008  Tanaka Akira  <akr@f...>
 
Index: mvm/thread_pthread.c
===================================================================
--- mvm/thread_pthread.c	(revision 17977)
+++ mvm/thread_pthread.c	(revision 17978)
@@ -801,7 +801,8 @@
 
 	pthread_attr_init(&attr);
 #ifdef PTHREAD_STACK_MIN
-	pthread_attr_setstacksize(&attr, PTHREAD_STACK_MIN);
+	pthread_attr_setstacksize(&attr,
+				  PTHREAD_STACK_MIN + (THREAD_DEBUG ? BUFSIZ : 0));
 #endif
 	err = pthread_create(&timer_thread_id, &attr, thread_timer, GET_VM());
 	if (err != 0) {
Index: mvm/iseq.c
===================================================================
--- mvm/iseq.c	(revision 17977)
+++ mvm/iseq.c	(revision 17978)
@@ -192,10 +192,10 @@
 
     iseq->coverage = Qfalse;
     if (!GET_THREAD()->parse_in_eval) {
-	extern VALUE rb_vm_get_coverages(void);
-	VALUE coverages = rb_vm_get_coverages();
+	extern VALUE rb_get_coverages(void);
+	VALUE coverages = rb_get_coverages();
 	if (RTEST(coverages)) {
-	    iseq->coverage = rb_hash_aref(coverages, filename);
+	    iseq->coverage = rb_hash_lookup(coverages, filename);
 	    if (NIL_P(iseq->coverage)) iseq->coverage = Qfalse;
 	}
     }
Index: mvm/string.c
===================================================================
--- mvm/string.c	(revision 17977)
+++ mvm/string.c	(revision 17978)
@@ -2513,11 +2513,12 @@
 {
     rb_encoding *enc;
     VALUE str;
-    char *sbeg, *s, *e;
+    char *sbeg, *s, *e, *last_alnum = 0;
     int c = -1;
     long l;
     char carry[ONIGENC_CODE_TO_MBC_MAXLEN] = "\1";
     int carry_pos = 0, carry_len = 1;
+    enum neighbor_char neighbor = NEIGHBOR_FOUND;
 
     str = rb_str_new5(orig, RSTRING_PTR(orig), RSTRING_LEN(orig));
     rb_enc_cr_str_copy_for_substr(str, orig);
@@ -2529,13 +2530,24 @@
     s = e = sbeg + RSTRING_LEN(str);
 
     while ((s = rb_enc_prev_char(sbeg, s, enc)) != 0) {
-        enum neighbor_char neighbor;
+	if (neighbor == NEIGHBOR_NOT_CHAR && last_alnum) {
+	    if (ISALPHA(*last_alnum) ? ISDIGIT(*s) :
+		ISDIGIT(*last_alnum) ? ISALPHA(*s) : 0) {
+		s = last_alnum;
+		break;
+	    }
+	}
 	if ((l = rb_enc_precise_mbclen(s, e, enc)) <= 0) continue;
         neighbor = enc_succ_alnum_char(s, l, enc, carry);
-        if (neighbor == NEIGHBOR_NOT_CHAR)
-            continue;
-        if (neighbor == NEIGHBOR_FOUND)
-            return str;
+        switch (neighbor) {
+	  case NEIGHBOR_NOT_CHAR:
+	    continue;
+	  case NEIGHBOR_FOUND:
+	    return str;
+	  case NEIGHBOR_WRAPPED:
+	    last_alnum = s;
+	    break;
+	}
         c = 1;
         carry_pos = s - sbeg;
         carry_len = l;
Index: mvm/lib/profiler.rb
===================================================================
--- mvm/lib/profiler.rb	(revision 17977)
+++ mvm/lib/profiler.rb	(revision 17978)
@@ -34,7 +34,7 @@
     total = Process.times[0] - @@start
     if total == 0 then total = 0.01 end
     data = @@map.values
-    data = data.sort_by{|x| x[2]}
+    data = data.sort_by{|x| -x[2]}
     sum = 0
     f.printf "  %%   cumulative   self              self     total\n"
     f.printf " time   seconds   seconds    calls  ms/call  ms/call  name\n"
Index: mvm/lib/rdoc/parsers/parse_c.rb
===================================================================
--- mvm/lib/rdoc/parsers/parse_c.rb	(revision 17977)
+++ mvm/lib/rdoc/parsers/parse_c.rb	(revision 17978)
@@ -36,7 +36,7 @@
     "rb_cTime"             => "Time",
     "rb_cTrueClass"        => "TrueClass",
     "rb_cStruct"           => "Struct",
-    "rb_cVM"               => "VM",
+    "rb_cRubyVM"           => "RubyVM",
     "rb_eException"        => "Exception",
     "rb_eStandardError"    => "StandardError",
     "rb_eSystemExit"       => "SystemExit",
Index: mvm/lib/profile.rb
===================================================================
--- mvm/lib/profile.rb	(revision 17977)
+++ mvm/lib/profile.rb	(revision 17978)
@@ -1,6 +1,6 @@
 require 'profiler'
 
-VM::InstructionSequence.compile_option = {
+RubyVM::InstructionSequence.compile_option = {
   :trace_instruction => true,
   :specialized_instruction => false
 }
Index: mvm/lib/debug.rb
===================================================================
--- mvm/lib/debug.rb	(revision 17977)
+++ mvm/lib/debug.rb	(revision 17978)
@@ -904,7 +904,7 @@
 set_trace_func proc { |event, file, line, id, binding, klass, *rest|
   DEBUGGER__.context.trace_func event, file, line, id, binding, klass
 }
-VM::InstructionSequence.compile_option = {
+RubyVM::InstructionSequence.compile_option = {
   trace_instruction: true
 }
 end
Index: mvm/compile.h
===================================================================
--- mvm/compile.h	(revision 17977)
+++ mvm/compile.h	(revision 17978)
@@ -164,11 +164,14 @@
 
 #define ADD_TRACE(seq, line, event) \
   do { \
-      if ((event) == RUBY_EVENT_LINE && iseq->coverage && RARRAY_PTR(iseq->coverage)[(line) - 1] == Qnil) { \
+      if ((event) == RUBY_EVENT_LINE && iseq->coverage && \
+	  RARRAY_PTR(iseq->coverage)[(line) - 1] == Qnil) { \
 	  RARRAY_PTR(iseq->coverage)[(line) - 1] = INT2FIX(0); \
 	  ADD_INSN1(seq, line, trace, INT2FIX(RUBY_EVENT_COVERAGE)); \
       } \
-      ADD_INSN1(seq, line, trace, INT2FIX(event)); \
+      if (iseq->compile_data->option->trace_instruction) { \
+	  ADD_INSN1(seq, line, trace, INT2FIX(event)); \
+      } \
   }while(0);
 
 /* add label */
Index: mvm/thread.c
===================================================================
--- mvm/thread.c	(revision 17977)
+++ mvm/thread.c	(revision 17978)
@@ -118,7 +118,17 @@
 } while(0)
 
 #if THREAD_DEBUG
+#ifdef HAVE_VA_ARGS_MACRO
+void rb_thread_debug(const char *file, int line, const char *fmt, ...);
+#define thread_debug(fmt, ...) rb_thread_debug(__FILE__, __LINE__, fmt, ##__VA_ARGS__)
+#define POSITION_FORMAT "%s:%d:"
+#define POSITION_ARGS ,file, line
+#else
 void rb_thread_debug(const char *fmt, ...);
+#define thread_debug rb_thread_debug
+#define POSITION_FORMAT
+#define POSITION_ARGS
+#endif
 
 # if THREAD_DEBUG < 0
 static int rb_thread_debug_enabled;
@@ -138,7 +148,6 @@
 # else
 # define rb_thread_debug_enabled THREAD_DEBUG
 # endif
-#define thread_debug rb_thread_debug
 #else
 #define thread_debug if(0)printf
 #endif
@@ -155,7 +164,7 @@
 
 #define DEBUG_OUT() \
   WaitForSingleObject(&debug_mutex, INFINITE); \
-  printf("%p - %s", GetCurrentThreadId(), buf); \
+  printf(POSITION_FORMAT"%p - %s" POSITION_ARGS, GetCurrentThreadId(), buf); \
   fflush(stdout); \
   ReleaseMutex(&debug_mutex);
 
@@ -164,7 +173,7 @@
 
 #define DEBUG_OUT() \
   pthread_mutex_lock(&debug_mutex); \
-  printf("%p - %s", pthread_self(), buf); \
+  printf(POSITION_FORMAT"%#"PRIxVALUE" - %s" POSITION_ARGS, (VALUE)pthread_self(), buf); \
   fflush(stdout); \
   pthread_mutex_unlock(&debug_mutex);
 
@@ -177,7 +186,11 @@
 static rb_thread_lock_t debug_mutex;
 
 void
-rb_thread_debug(const char *fmt, ...)
+rb_thread_debug(
+#ifdef HAVE_VA_ARGS_MACRO
+    const char *file, int line,
+#endif
+    const char *fmt, ...)
 {
     va_list args;
     char buf[BUFSIZ];
@@ -710,9 +723,47 @@
 }
 
 static void
+getclockofday(struct timeval *tp)
+{
+#if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)
+    struct timespec ts;
+
+    if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0) {
+	tp->tv_sec = ts.tv_sec;
+	tp->tv_usec = ts.tv_nsec / 1000;
+    } else
+#endif
+    {
+        gettimeofday(tp, NULL);
+    }
+}
+
+static void
 sleep_timeval(rb_thread_t *th, struct timeval tv)
 {
-    native_sleep(th, &tv, 0);
+    struct timeval to, tvn;
+
+    getclockofday(&to);
+    to.tv_sec += tv.tv_sec;
+    if ((to.tv_usec += tv.tv_usec) >= 1000000) {
+	to.tv_sec++;
+	to.tv_usec -= 1000000;
+    }
+
+    for (;;) {
+	native_sleep(th, &tv, 0);
+	getclockofday(&tvn);
+	if (to.tv_sec < tvn.tv_sec) break;
+	if (to.tv_sec == tvn.tv_sec && to.tv_usec <= tvn.tv_usec) break;
+	thread_debug("sleep_timeval: %ld.%.6ld > %ld.%.6ld\n",
+		     (long)to.tv_sec, to.tv_usec,
+		     (long)tvn.tv_sec, tvn.tv_usec);
+	tv.tv_sec = to.tv_sec - tvn.tv_sec;
+	if ((tv.tv_usec = to.tv_usec - tvn.tv_usec) < 0) {
+	    --tv.tv_sec;
+	    tv.tv_usec += 1000000;
+	}
+    }
 }
 
 void
@@ -2124,8 +2175,8 @@
 static void
 clear_coverage(void)
 {
-    extern VALUE rb_vm_get_coverages(void);
-    VALUE coverages = rb_vm_get_coverages();
+    extern VALUE rb_get_coverages(void);
+    VALUE coverages = rb_get_coverages();
     if (RTEST(coverages)) {
 	st_foreach(RHASH_TBL(coverages), clear_coverage_i, 0);
     }
@@ -3603,7 +3654,7 @@
 update_coverage(rb_event_flag_t event, VALUE proc, VALUE self, ID id, VALUE klass)
 {
     VALUE coverage = GET_THREAD()->cfp->iseq->coverage;
-    if (coverage) {
+    if (coverage && RBASIC(coverage)->klass == 0) {
 	long line = rb_sourceline() - 1;
 	long count;
 	if (RARRAY_PTR(coverage)[line] == Qnil) {
@@ -3616,17 +3667,22 @@
     }
 }
 
+VALUE
+rb_get_coverages(void)
+{
+    return rb_vm_specific_ptr(rb_vmkey_coverages);
+}
+
 void
-rb_enable_coverages(void)
+rb_set_coverages(VALUE coverages)
 {
-    VALUE *coverages = rb_vm_specific_ptr(rb_vmkey_coverages);
-    VALUE rb_mCoverage;
+    *rb_vm_specific_ptr(rb_vmkey_coverages) = coverages;
+    rb_add_event_hook(update_coverage, RUBY_EVENT_COVERAGE, Qnil);
+}
 
-    if (!RTEST(*coverages)) {
-	extern VALUE rb_vm_get_coverages(void);
-	*coverages = rb_hash_new();
-	rb_add_event_hook(update_coverage, RUBY_EVENT_COVERAGE, Qnil);
-	rb_mCoverage = rb_define_module("Coverage");
-	rb_define_module_function(rb_mCoverage, "result", rb_vm_get_coverages, 0);
-    }
+void
+rb_reset_coverages(void)
+{
+    *rb_vm_specific_ptr(rb_vmkey_coverages) = Qfalse;
+    rb_remove_event_hook(update_coverage);
 }
Index: mvm/dir.c
===================================================================
--- mvm/dir.c	(revision 17977)
+++ mvm/dir.c	(revision 17978)
@@ -83,97 +83,38 @@
 #define FNM_NOMATCH	1
 #define FNM_ERROR	2
 
-#define downcase(c) (nocase && ISUPPER(c) ? TOLOWER(c) : (c))
-#define compare(c1, c2) (((unsigned char)(c1)) - ((unsigned char)(c2)))
+# define Next(p, e, enc) (p + rb_enc_mbclen(p, e, enc))
+# define Inc(p, e, enc) ((p) = Next(p, e, enc))
 
-/* caution: in case *p == '\0'
-   Next(p) == p + 1 in single byte environment
-   Next(p) == p     in multi byte environment
-*/
-#if defined(CharNext)
-# define Next(p) CharNext(p)
-#elif defined(DJGPP)
-# define Next(p) ((p) + mblen(p, RUBY_MBCHAR_MAXSIZE))
-#elif defined(__EMX__)
-# define Next(p) ((p) + emx_mblen(p))
-static inline int
-emx_mblen(const char *p)
-{
-    int n = mblen(p, RUBY_MBCHAR_MAXSIZE);
-    return (n < 0) ? 1 : n;
-}
-#endif
-
-#ifndef Next /* single byte environment */
-# define Next(p) ((p) + 1)
-# define Inc(p) (++(p))
-# define Compare(p1, p2) (compare(downcase(*(p1)), downcase(*(p2))))
-#else /* multi byte environment */
-# define Inc(p) ((p) = Next(p))
-# define Compare(p1, p2) (CompareImpl(p1, p2, nocase))
 static int
-CompareImpl(const char *p1, const char *p2, int nocase)
+char_casecmp(const char *p1, const char *p2, rb_encoding *enc, const int nocase)
 {
-    const int len1 = Next(p1) - p1;
-    const int len2 = Next(p2) - p2;
-#ifdef _WIN32
-    char buf1[10], buf2[10]; /* large enough? */
-#endif
+    const char *p1end, *p2end;
+    int c1, c2;
 
-    if (len1 < 0 || len2 < 0) {
-	rb_fatal("CompareImpl: negative len");
-    }
+    if (!*p1) return *p1;
+    if (!*p2) return -*p2;
+    p1end = p1 + strlen(p1);
+    p2end = p2 + strlen(p2);
+    c1 = rb_enc_codepoint(p1, p1end, enc);
+    c2 = rb_enc_codepoint(p2, p2end, enc);
 
-    if (len1 == 0) return  len2;
-    if (len2 == 0) return -len1;
-
-#ifdef _WIN32
-    if (nocase && rb_w32_iswinnt()) {
-	if (len1 > 1) {
-	    if (len1 >= sizeof(buf1)) {
-		rb_fatal("CompareImpl: too large len");
-	    }
-	    memcpy(buf1, p1, len1);
-	    buf1[len1] = '\0';
-	    CharLower(buf1);
-	    p1 = buf1; /* trick */
-	}
-	if (len2 > 1) {
-	    if (len2 >= sizeof(buf2)) {
-		rb_fatal("CompareImpl: too large len");
-	    }
-	    memcpy(buf2, p2, len2);
-	    buf2[len2] = '\0';
-	    CharLower(buf2);
-	    p2 = buf2; /* trick */
-	}
+    if (c1 == c2) return 0;
+    if (nocase) {
+	c1 = rb_enc_toupper(c1, enc);
+	c2 = rb_enc_toupper(c2, enc);
     }
-#endif
-    if (len1 == 1)
-	if (len2 == 1)
-	    return compare(downcase(*p1), downcase(*p2));
-	else {
-	    const int ret = compare(downcase(*p1), *p2);
-	    return ret ? ret : -1;
-	}
-    else
-	if (len2 == 1) {
-	    const int ret = compare(*p1, downcase(*p2));
-	    return ret ? ret : 1;
-	}
-	else {
-	    const int ret = memcmp(p1, p2, len1 < len2 ? len1 : len2);
-	    return ret ? ret : len1 - len2;
-	}
+    return c1 - c2;
 }
-#endif /* environment */
 
 static char *
 bracket(
     const char *p, /* pattern (next to '[') */
     const char *s, /* string */
-    int flags)
+    int flags,
+    rb_encoding *enc)
 {
+    const char *pend = p + strlen(p);
     const int nocase = flags & FNM_CASEFOLD;
     const int escape = !(flags & FNM_NOESCAPE);
 
@@ -190,19 +131,19 @@
 	    t1++;
 	if (!*t1)
 	    return NULL;
-	p = Next(t1);
+	p = Next(t1, pend, enc);
 	if (p[0] == '-' && p[1] != ']') {
 	    const char *t2 = p + 1;
 	    if (escape && *t2 == '\\')
 		t2++;
 	    if (!*t2)
 		return NULL;
-	    p = Next(t2);
-	    if (!ok && Compare(t1, s) <= 0 && Compare(s, t2) <= 0)
+	    p = Next(t2, pend, enc);
+	    if (!ok && char_casecmp(t1, s, enc, nocase) <= 0 && char_casecmp(s, t2, enc, nocase) <= 0)
 		ok = 1;
 	}
 	else
-	    if (!ok && Compare(t1, s) == 0)
+	    if (!ok && char_casecmp(t1, s, enc, nocase) == 0)
 		ok = 1;
     }
 
@@ -222,7 +163,8 @@
 fnmatch_helper(
     const char **pcur, /* pattern */
     const char **scur, /* string */
-    int flags)
+    int flags,
+    rb_encoding *enc)
 {
     const int period = !(flags & FNM_DOTMATCH);
     const int pathname = flags & FNM_PATHNAME;
@@ -233,7 +175,9 @@
     const char *stmp = 0;
 
     const char *p = *pcur;
+    const char *pend = p + strlen(p);
     const char *s = *scur;
+    const char *send = s + strlen(s);
 
     if (period && *s == '.' && *UNESCAPE(p) != '.') /* leading period */
 	RETURN(FNM_NOMATCH);
@@ -256,16 +200,16 @@
 	    if (ISEND(s))
 		RETURN(FNM_NOMATCH);
 	    p++;
-	    Inc(s);
+	    Inc(s, send, enc);
 	    continue;
 
 	  case '[': {
 	    const char *t;
 	    if (ISEND(s))
 		RETURN(FNM_NOMATCH);
-	    if ((t = bracket(p + 1, s, flags)) != 0) {
+	    if ((t = bracket(p + 1, s, flags, enc)) != 0) {
 		p = t;
-		Inc(s);
+		Inc(s, send, enc);
 		continue;
 	    }
 	    goto failed;
@@ -278,16 +222,16 @@
 	    RETURN(ISEND(p) ? 0 : FNM_NOMATCH);
 	if (ISEND(p))
 	    goto failed;
-	if (Compare(p, s) != 0)
+	if (char_casecmp(p, s, enc, nocase) != 0)
 	    goto failed;
-	Inc(p);
-	Inc(s);
+	Inc(p, pend, enc);
+	Inc(s, send, enc);
 	continue;
 
       failed: /* try next '*' position */
 	if (ptmp && stmp) {
 	    p = ptmp;
-	    Inc(stmp); /* !ISEND(*stmp) */
+	    Inc(stmp, send, enc); /* !ISEND(*stmp) */
 	    s = stmp;
 	    continue;
 	}
@@ -297,10 +241,14 @@
 
 static int
 fnmatch(
-    const char *p, /* pattern */
-    const char *s, /* string */
+    const char *pattern,
+    rb_encoding *enc,
+    const char *string,
     int flags)
 {
+    const char *p = pattern;
+    const char *s = string;
+    const char *send = s + strlen(string);
     const int period = !(flags & FNM_DOTMATCH);
     const int pathname = flags & FNM_PATHNAME;
 
@@ -314,8 +262,8 @@
 		ptmp = p;
 		stmp = s;
 	    }
-	    if (fnmatch_helper(&p, &s, flags) == 0) {
-		while (*s && *s != '/') Inc(s);
+	    if (fnmatch_helper(&p, &s, flags, enc) == 0) {
+		while (*s && *s != '/') Inc(s, send, enc);
 		if (*p && *s) {
 		    p++;
 		    s++;
@@ -326,7 +274,7 @@
 	    }
 	    /* failed : try next recursion */
 	    if (ptmp && stmp && !(period && *stmp == '.')) {
-		while (*stmp && *stmp != '/') Inc(stmp);
+		while (*stmp && *stmp != '/') Inc(stmp, send, enc);
 		if (*stmp) {
 		    p = ptmp;
 		    stmp++;
@@ -338,7 +286,7 @@
 	}
     }
     else
-	return fnmatch_helper(&p, &s, flags);
+	return fnmatch_helper(&p, &s, flags, enc);
 }
 
 struct dir_data {
@@ -1057,12 +1005,13 @@
 
 /* Return nonzero if S has any special globbing chars in it.  */
 static int
-has_magic(const char *s, int flags)
+has_magic(const char *s, int flags, rb_encoding *enc)
 {
     const int escape = !(flags & FNM_NOESCAPE);
     const int nocase = flags & FNM_CASEFOLD;
 
     register const char *p = s;
+    register const char *pend = p + strlen(p);
     register char c;
 
     while ((c = *p++) != 0) {
@@ -1082,7 +1031,7 @@
 		return 1;
 	}
 
-	p = Next(p-1);
+	p = Next(p-1, pend, enc);
     }
 
     return 0;
@@ -1090,11 +1039,12 @@
 
 /* Find separator in globbing pattern. */
 static char *
-find_dirsep(const char *s, int flags)
+find_dirsep(const char *s, int flags, rb_encoding *enc)
 {
     const int escape = !(flags & FNM_NOESCAPE);
 
     register const char *p = s;
+    register const char *pend = p + strlen(p);
     register char c;
     int open = 0;
 
@@ -1118,7 +1068,7 @@
 	    continue;
 	}
 
-	p = Next(p-1);
+	p = Next(p-1, pend, enc);
     }
 
     return (char *)p-1;
@@ -1126,8 +1076,9 @@
 
 /* Remove escaping backslashes */
 static void
-remove_backslashes(char *p)
+remove_backslashes(char *p, rb_encoding *enc)
 {
+    register const char *pend = p + strlen(p);
     char *t = p;
     char *s = p;
 
@@ -1139,7 +1090,7 @@
 	    s = ++p;
 	    if (!*p) break;
 	}
-	Inc(p);
+	Inc(p, pend, enc);
     }
 
     while (*p++);
@@ -1160,7 +1111,7 @@
 static void glob_free_pattern(struct glob_pattern *list);
 
 static struct glob_pattern *
-glob_make_pattern(const char *p, int flags)
+glob_make_pattern(const char *p, int flags, rb_encoding *enc)
 {
     struct glob_pattern *list, *tmp, **tail = &list;
     int dirsep = 0; /* pattern is terminated with '/' */
@@ -1176,7 +1127,7 @@
 	    dirsep = 1;
 	}
 	else {
-	    const char *m = find_dirsep(p, flags);
+	    const char *m = find_dirsep(p, flags, enc);
 	    char *buf = GLOB_ALLOC_N(char, m-p+1);
 	    if (!buf) {
 		GLOB_FREE(tmp);
@@ -1184,7 +1135,7 @@
 	    }
 	    memcpy(buf, p, m-p);
 	    buf[m-p] = '\0';
-	    tmp->type = has_magic(buf, flags) ? MAGICAL : PLAIN;
+	    tmp->type = has_magic(buf, flags, enc) ? MAGICAL : PLAIN;
 	    tmp->str = buf;
 	    if (*m) {
 		dirsep = 1;
@@ -1257,9 +1208,10 @@
 #endif
 
 struct glob_args {
-    void (*func)(const char *, VALUE);
+    void (*func)(const char *, VALUE, void *);
     const char *path;
     VALUE value;
+    rb_encoding *enc;
 };
 
 static VALUE
@@ -1267,11 +1219,11 @@
 {
     struct glob_args *args = (struct glob_args *)val;
 
-    (*args->func)(args->path, args->value);
+    (*args->func)(args->path, args->value, args->enc);
     return Qnil;
 }
 
-#define glob_call_func(func, path, arg) (*func)(path, arg)
+#define glob_call_func(func, path, arg, enc) (*func)(path, arg, enc)
 
 static int
 glob_helper(
@@ -1283,7 +1235,8 @@
     struct glob_pattern **end,
     int flags,
     ruby_glob_func *func,
-    VALUE arg)
+    VALUE arg,
+    rb_encoding *enc)
 {
     struct stat st;
     int status = 0;
@@ -1337,13 +1290,13 @@
 	    }
 	}
 	if (match_all && exist == YES) {
-	    status = glob_call_func(func, path, arg);
+	    status = glob_call_func(func, path, arg, enc);
 	    if (status) return status;
 	}
 	if (match_dir && isdir == YES) {
 	    char *tmp = join_path(path, dirsep, "");
 	    if (!tmp) return -1;
-	    status = glob_call_func(func, tmp, arg);
+	    status = glob_call_func(func, tmp, arg, enc);
 	    GLOB_FREE(tmp);
 	    if (status) return status;
 	}
@@ -1365,7 +1318,7 @@
 		break;
 	    }
 	    if (recursive && strcmp(dp->d_name, ".") != 0 && strcmp(dp->d_name, "..") != 0
-		&& fnmatch("*", dp->d_name, flags) == 0) {
+		&& fnmatch("*", rb_usascii_encoding(), dp->d_name, flags) == 0) {
 #ifndef _WIN32
 		if (do_lstat(buf, &st, flags) == 0)
 		    new_isdir = S_ISDIR(st.st_mode) ? YES : S_ISLNK(st.st_mode) ? UNKNOWN : NO;
@@ -1391,12 +1344,13 @@
 		    p = p->next; /* 0 times recursion */
 		}
 		if (p->type == PLAIN || p->type == MAGICAL) {
-		    if (fnmatch(p->str, dp->d_name, flags) == 0)
+		    if (fnmatch(p->str, enc, dp->d_name, flags) == 0)
 			*new_end++ = p->next;
 		}
 	    }
 
-	    status = glob_helper(buf, 1, YES, new_isdir, new_beg, new_end, flags, func, arg);
+	    status = glob_helper(buf, 1, YES, new_isdir, new_beg, new_end,
+				 flags, func, arg, enc);
 	    GLOB_FREE(buf);
 	    GLOB_FREE(new_beg);
 	    if (status) break;
@@ -1422,7 +1376,7 @@
 		    break;
 		}
 		strcpy(name, (*cur)->str);
-		if (escape) remove_backslashes(name);
+		if (escape) remove_backslashes(name, enc);
 
 		new_beg = new_end = GLOB_ALLOC_N(struct glob_pattern *, end - beg);
 		if (!new_beg) {
@@ -1432,7 +1386,7 @@
 		}
 		*new_end++ = (*cur)->next;
 		for (cur2 = cur + 1; cur2 < copy_end; ++cur2) {
-		    if (*cur2 && fnmatch((*cur2)->str, name, flags) == 0) {
+		    if (*cur2 && fnmatch((*cur2)->str, enc, name, flags) == 0) {
 			*new_end++ = (*cur2)->next;
 			*cur2 = 0;
 		    }
@@ -1445,7 +1399,8 @@
 		    status = -1;
 		    break;
 		}
-		status = glob_helper(buf, 1, UNKNOWN, UNKNOWN, new_beg, new_end, flags, func, arg);
+		status = glob_helper(buf, 1, UNKNOWN, UNKNOWN, new_beg,
+				     new_end, flags, func, arg, enc);
 		GLOB_FREE(buf);
 		GLOB_FREE(new_beg);
 		if (status) break;
@@ -1459,7 +1414,7 @@
 }
 
 static int
-ruby_glob0(const char *path, int flags, ruby_glob_func *func, VALUE arg)
+ruby_glob0(const char *path, int flags, ruby_glob_func *func, VALUE arg, rb_encoding *enc)
 {
     struct glob_pattern *list;
     const char *root, *start;
@@ -1481,12 +1436,12 @@
     MEMCPY(buf, start, char, n);
     buf[n] = '\0';
 
-    list = glob_make_pattern(root, flags);
+    list = glob_make_pattern(root, flags, enc);
     if (!list) {
 	GLOB_FREE(buf);
 	return -1;
     }
-    status = glob_helper(buf, 0, UNKNOWN, UNKNOWN, &list, &list + 1, flags, func, arg);
+    status = glob_helper(buf, 0, UNKNOWN, UNKNOWN, &list, &list + 1, flags, func, arg, enc);
     glob_free_pattern(list);
     GLOB_FREE(buf);
 
@@ -1496,11 +1451,12 @@
 int
 ruby_glob(const char *path, int flags, ruby_glob_func *func, VALUE arg)
 {
-    return ruby_glob0(path, flags & ~GLOB_VERBOSE, func, arg);
+    return ruby_glob0(path, flags & ~GLOB_VERBOSE, func, arg,
+		      rb_ascii8bit_encoding());
 }
 
 static int
-rb_glob_caller(const char *path, VALUE a)
+rb_glob_caller(const char *path, VALUE a, void *enc)
 {
     int status;
     struct glob_args *args = (struct glob_args *)a;
@@ -1511,38 +1467,46 @@
 }
 
 static int
-rb_glob2(const char *path, int flags, void (*func)(const char *, VALUE), VALUE arg)
+rb_glob2(const char *path, int flags,
+	 void (*func)(const char *, VALUE, void *), VALUE arg,
+	 rb_encoding* enc)
 {
     struct glob_args args;
 
     args.func = func;
     args.value = arg;
+    args.enc = enc;
 
     if (flags & FNM_SYSCASE) {
 	rb_warning("Dir.glob() ignores File::FNM_CASEFOLD");
     }
 
-    return ruby_glob0(path, flags | GLOB_VERBOSE, rb_glob_caller, (VALUE)&args);
+    return ruby_glob0(path, flags | GLOB_VERBOSE, rb_glob_caller, (VALUE)&args,
+		      enc);
 }
 
 void
-rb_glob(const char *path, void (*func)(const char *, VALUE), VALUE arg)
+rb_glob(const char *path, void (*func)(const char *, VALUE, void *), VALUE arg)
 {
-    int status = rb_glob2(path, 0, func, arg);
+    int status = rb_glob2(path, 0, func, arg, rb_ascii8bit_encoding());
     if (status) GLOB_JUMP_TAG(status);
 }
 
 static void
-push_pattern(const char *path, VALUE ary)
+push_pattern(const char *path, VALUE ary, void *enc)
 {
-    rb_ary_push(ary, rb_tainted_str_new2(path));
+    VALUE vpath = rb_tainted_str_new2(path);
+    rb_enc_associate(vpath, enc);
+    rb_ary_push(ary, vpath);
 }
 
-int
-ruby_brace_expand(const char *str, int flags, ruby_glob_func *func, VALUE arg)
+static int
+ruby_brace_expand(const char *str, int flags, ruby_glob_func *func, VALUE arg,
+		  rb_encoding *enc)
 {
     const int escape = !(flags & FNM_NOESCAPE);
     const char *p = str;
+    const char *pend = p + strlen(p);
     const char *s = p;
     const char *lbrace = 0, *rbrace = 0;
     int nest = 0, status = 0;
@@ -1558,7 +1522,7 @@
 	if (*p == '\\' && escape) {
 	    if (!*++p) break;
 	}
-	Inc(p);
+	Inc(p, pend, enc);
     }
 
     if (lbrace && rbrace) {
@@ -1578,17 +1542,17 @@
 		if (*p == '\\' && escape) {
 		    if (++p == rbrace) break;
 		}
-		Inc(p);
+		Inc(p, pend, enc);
 	    }
 	    memcpy(buf+shift, t, p-t);
 	    strcpy(buf+shift+(p-t), rbrace+1);
-	    status = ruby_brace_expand(buf, flags, func, arg);
+	    status = ruby_brace_expand(buf, flags, func, arg, enc);
 	    if (status) break;
 	}
 	GLOB_FREE(buf);
     }
     else if (!lbrace && !rbrace) {
-	status = (*func)(s, arg);
+	status = (*func)(s, arg, enc);
     }
 
     return status;
@@ -1601,38 +1565,44 @@
 };
 
 static int
-glob_brace(const char *path, VALUE val)
+glob_brace(const char *path, VALUE val, void *enc)
 {
     struct brace_args *arg = (struct brace_args *)val;
 
-    return ruby_glob0(path, arg->flags, arg->func, arg->value);
+    return ruby_glob0(path, arg->flags, arg->func, arg->value, enc);
 }
 
 static int
-ruby_brace_glob0(const char *str, int flags, ruby_glob_func *func, VALUE arg)
+ruby_brace_glob0(const char *str, int flags, ruby_glob_func *func, VALUE arg,
+		 rb_encoding* enc)
 {
     struct brace_args args;
 
     args.func = func;
     args.value = arg;
     args.flags = flags;
-    return ruby_brace_expand(str, flags, glob_brace, (VALUE)&args);
+    return ruby_brace_expand(str, flags, glob_brace, (VALUE)&args, enc);
 }
 
 int
 ruby_brace_glob(const char *str, int flags, ruby_glob_func *func, VALUE arg)
 {
-    return ruby_brace_glob0(str, flags & ~GLOB_VERBOSE, func, arg);
+    return ruby_brace_glob0(str, flags & ~GLOB_VERBOSE, func, arg,
+			    rb_ascii8bit_encoding());
 }
 
 static int
-push_glob(VALUE ary, const char *str, int flags)
+push_glob(VALUE ary, VALUE str, int flags)
 {
     struct glob_args args;
+    rb_encoding *enc = rb_enc_get(str);
 
     args.func = push_pattern;
     args.value = ary;
-    return ruby_brace_glob0(str, flags | GLOB_VERBOSE, rb_glob_caller, (VALUE)&args);
+    args.enc = enc;
+
+    return ruby_brace_glob0(RSTRING_PTR(str), flags | GLOB_VERBOSE,
+			    rb_glob_caller, (VALUE)&args, enc);
 }
 
 static VALUE
@@ -1645,11 +1615,13 @@
     ary = rb_ary_new();
 
     while (offset < RSTRING_LEN(str)) {
-	int status = push_glob(ary, RSTRING_PTR(str) + offset, flags);
 	char *p, *pend;
+	int status;
+	p = RSTRING_PTR(str) + offset;
+	status = push_glob(ary, rb_enc_str_new(p, strlen(p), rb_enc_get(str)),
+			   flags);
 	if (status) GLOB_JUMP_TAG(status);
 	if (offset >= RSTRING_LEN(str)) break;
-	p = RSTRING_PTR(str) + offset;
 	p += strlen(p) + 1;
 	pend = RSTRING_PTR(str) + RSTRING_LEN(str);
 	while (p < pend && !*p)
@@ -1670,7 +1642,7 @@
 	int status;
 	VALUE str = argv[i];
 	StringValue(str);
-	status = push_glob(ary, RSTRING_PTR(str), flags);
+	status = push_glob(ary, str, flags);
 	if (status) GLOB_JUMP_TAG(status);
     }
 
@@ -1941,7 +1913,8 @@
     StringValue(pattern);
     FilePathStringValue(path);
 
-    if (fnmatch(RSTRING_PTR(pattern), RSTRING_PTR(path), flags) == 0)
+    if (fnmatch(RSTRING_PTR(pattern), rb_enc_get(pattern), RSTRING_PTR(path),
+		flags) == 0)
 	return Qtrue;
 
     return Qfalse;
Index: mvm/parse.y
===================================================================
--- mvm/parse.y	(revision 17977)
+++ mvm/parse.y	(revision 17978)
@@ -4672,12 +4672,13 @@
 static VALUE
 coverage(const char *f, int n)
 {
-    extern VALUE rb_vm_get_coverages(void);
-    VALUE coverages = rb_vm_get_coverages();
-    if (RTEST(coverages)) {
+    extern VALUE rb_get_coverages(void);
+    VALUE coverages = rb_get_coverages();
+    if (RTEST(coverages) && RBASIC(coverages)->klass == 0) {
 	VALUE fname = rb_str_new2(f);
 	VALUE lines = rb_ary_new2(n);
 	int i;
+	RBASIC(lines)->klass = 0;
 	for (i = 0; i < n; i++) RARRAY_PTR(lines)[i] = Qnil;
 	RARRAY(lines)->len = n;
 	rb_hash_aset(coverages, fname, lines);
@@ -4718,9 +4719,6 @@
 
     parser_prepare(parser);
     n = yyparse((void*)parser);
-    if (ruby_coverage) {
-	rb_ary_freeze(ruby_coverage);
-    }
     ruby_debug_lines = 0;
     ruby_coverage = 0;
     compile_for_eval = 0;
Index: mvm/ext/coverage/coverage.c
===================================================================
--- mvm/ext/coverage/coverage.c	(revision 17977)
+++ mvm/ext/coverage/coverage.c	(revision 17978)
@@ -10,15 +10,67 @@
 
 #include "ruby.h"
 
-extern void rb_enable_coverages(void);
+static VALUE rb_mCoverage;
 
+extern VALUE rb_get_coverages(void);
+extern void rb_set_coverages(VALUE);
+extern void rb_reset_coverages(void);
+
+/*
+ * call-seq:
+ *    Coverage.start  => nil
+ *
+ * Enables coverage measurement.
+ */
+static VALUE
+rb_coverage_start(VALUE klass)
+{
+    if (!RTEST(rb_get_coverages())) {
+	VALUE coverages = rb_hash_new();
+	RBASIC(coverages)->klass = 0;
+	rb_set_coverages(coverages);
+    }
+}
+
+static int
+coverage_result_i(st_data_t key, st_data_t val, st_data_t dummy)
+{
+    VALUE coverage = (VALUE)val;
+    RBASIC(coverage)->klass = rb_cArray;
+    rb_ary_freeze(coverage);
+    return ST_CONTINUE;
+}
+
+/*
+ *  call-seq:
+ *     Coverage.result  => hash
+ *
+ * Returns a hash that contains filename as key and coverage array as value
+ * and disables coverage measurement.
+ */
+static VALUE
+rb_coverage_result(VALUE klass)
+{
+    VALUE coverages = rb_get_coverages();
+    if (!RTEST(coverages)) {
+	rb_raise(rb_eRuntimeError, "coverage measurement is not enabled");
+    }
+    RBASIC(coverages)->klass = rb_cHash;
+    st_foreach(RHASH_TBL(coverages), coverage_result_i, 0);
+    rb_hash_freeze(coverages);
+    rb_reset_coverages();
+    return coverages;
+}
+
 /* Coverage provides coverage measurement feature for Ruby.
+ * This feature is experimental, so these APIs may be changed in future.
  *
  * = Usage
  *
  * (1) require "coverage.so"
- * (2) require or load Ruby source file
- * (3) Coverage.result will return a hash that contains filename as key and
+ * (2) do Coverage.start
+ * (3) require or load Ruby source file
+ * (4) Coverage.result will return a hash that contains filename as key and
  *     coverage array as value.
  *
  * = Example
@@ -37,11 +89,14 @@
  *   [EOF]
  *
  *   require "coverage.so"
+ *   Coverage.start
  *   require "foo.rb"
- *   p COVERAGE__  #=> {"foo.rb"=>[1, 1, 10, nil, nil, 1, 1, nil, 0, nil]}
+ *   p Coverage.result  #=> {"foo.rb"=>[1, 1, 10, nil, nil, 1, 1, nil, 0, nil]}
  */
 void
 Init_coverage(void)
 {
-    rb_enable_coverages();
+    rb_mCoverage = rb_define_module("Coverage");
+    rb_define_module_function(rb_mCoverage, "start", rb_coverage_start, 0);
+    rb_define_module_function(rb_mCoverage, "result", rb_coverage_result, 0);
 }
Index: mvm/ext/win32ole/win32ole.c
===================================================================
--- mvm/ext/win32ole/win32ole.c	(revision 17977)
+++ mvm/ext/win32ole/win32ole.c	(revision 17978)
@@ -118,7 +118,7 @@
 
 #define WC2VSTR(x) ole_wc2vstr((x), TRUE)
 
-#define WIN32OLE_VERSION "1.2.0"
+#define WIN32OLE_VERSION "1.2.3"
 
 typedef HRESULT (STDAPICALLTYPE FNCOCREATEINSTANCEEX)
     (REFCLSID, IUnknown*, DWORD, COSERVERINFO*, DWORD, MULTI_QI*);
@@ -424,8 +424,11 @@
 static VALUE ole_type_helpcontext(ITypeInfo *pTypeInfo);
 static VALUE foletype_helpcontext(VALUE self);
 static VALUE foletype_ole_typelib(VALUE self);
-static VALUE ole_type_impl_ole_types(ITypeInfo *pTypeInfo);
+static VALUE ole_type_impl_ole_types(ITypeInfo *pTypeInfo, int implflags);
 static VALUE foletype_impl_ole_types(VALUE self);
+static VALUE foletype_source_ole_types(VALUE self);
+static VALUE foletype_default_event_sources(VALUE self);
+static VALUE foletype_default_ole_types(VALUE self);
 static VALUE foletype_inspect(VALUE self);
 static VALUE ole_variables(ITypeInfo *pTypeInfo);
 static VALUE foletype_variables(VALUE self);
@@ -498,6 +501,8 @@
 static VALUE ole_search_event(VALUE ary, VALUE ev, BOOL  *is_default);
 static void ary2ptr_dispparams(VALUE ary, DISPPARAMS *pdispparams);
 static HRESULT find_iid(VALUE ole, char *pitf, IID *piid, ITypeInfo **ppTypeInfo);
+static HRESULT find_coclass(ITypeInfo *pTypeInfo, TYPEATTR *pTypeAttr, ITypeInfo **pTypeInfo2, TYPEATTR **pTypeAttr2);
+static HRESULT find_default_source_from_typeinfo(ITypeInfo *pTypeInfo, TYPEATTR *pTypeAttr, ITypeInfo **ppTypeInfo);
 static HRESULT find_default_source(VALUE ole, IID *piid, ITypeInfo **ppTypeInfo);
 static void ole_event_free(struct oleeventdata *poleev);
 static VALUE fev_s_allocate(VALUE klass);
@@ -5756,7 +5761,7 @@
 }
 
 static VALUE
-ole_type_impl_ole_types(ITypeInfo *pTypeInfo)
+ole_type_impl_ole_types(ITypeInfo *pTypeInfo, int implflags)
 {
     HRESULT hr;
     ITypeInfo *pRefTypeInfo;
@@ -5782,9 +5787,12 @@
         hr = pTypeInfo->lpVtbl->GetRefTypeInfo(pTypeInfo, href, &pRefTypeInfo);
         if (FAILED(hr)) 
             continue;
-        type = ole_type_from_itypeinfo(pRefTypeInfo);
-        if (type != Qnil) {
-            rb_ary_push(types, type);
+
+        if ((flags & implflags) == implflags) {
+            type = ole_type_from_itypeinfo(pRefTypeInfo);
+            if (type != Qnil) {
+                rb_ary_push(types, type);
+            }
         }
 
         OLE_RELEASE(pRefTypeInfo);
@@ -5807,10 +5815,63 @@
 {
     struct oletypedata *ptype;
     Data_Get_Struct(self, struct oletypedata, ptype);
-    return ole_type_impl_ole_types(ptype->pTypeInfo);
+    return ole_type_impl_ole_types(ptype->pTypeInfo, 0);
 }
 
+/*
+ *  call-seq:
+ *     WIN32OLE_TYPE#source_ole_types
+ * 
+ *  Returns the array of WIN32OLE_TYPE object which is implemented by the WIN32OLE_TYPE 
+ *  object and having IMPLTYPEFLAG_FSOURCE. 
+ *     tobj = WIN32OLE_TYPE.new('Microsoft Internet Controls', "InternetExplorer") 
+ *     p tobj.source_ole_types
+ *     # => [#<WIN32OLE_TYPE:DWebBrowserEvents2>, #<WIN32OLE_TYPE:DWebBrowserEvents>]
+ */
 static VALUE
+foletype_source_ole_types(VALUE self)
+{
+    struct oletypedata *ptype;
+    Data_Get_Struct(self, struct oletypedata, ptype);
+    return ole_type_impl_ole_types(ptype->pTypeInfo, IMPLTYPEFLAG_FSOURCE);
+}
+
+/*
+ *  call-seq:
+ *     WIN32OLE_TYPE#default_event_sources
+ * 
+ *  Returns the array of WIN32OLE_TYPE object which is implemented by the WIN32OLE_TYPE 
+ *  object and having IMPLTYPEFLAG_FSOURCE and IMPLTYPEFLAG_FDEFAULT. 
+ *     tobj = WIN32OLE_TYPE.new('Microsoft Internet Controls', "InternetExplorer") 
+ *     p tobj.default_event_sources  # => [#<WIN32OLE_TYPE:DWebBrowserEvents2>]
+ */
+static VALUE
+foletype_default_event_sources(VALUE self)
+{
+    struct oletypedata *ptype;
+    Data_Get_Struct(self, struct oletypedata, ptype);
+    return ole_type_impl_ole_types(ptype->pTypeInfo, IMPLTYPEFLAG_FSOURCE|IMPLTYPEFLAG_FDEFAULT);
+}
+
+/*
+ *  call-seq:
+ *     WIN32OLE_TYPE#default_ole_types
+ * 
+ *  Returns the array of WIN32OLE_TYPE object which is implemented by the WIN32OLE_TYPE 
+ *  object and having IMPLTYPEFLAG_FDEFAULT.
+ *     tobj = WIN32OLE_TYPE.new('Microsoft Internet Controls', "InternetExplorer") 
+ *     p tobj.default_ole_types
+ *     # => [#<WIN32OLE_TYPE:IWebBrowser2>, #<WIN32OLE_TYPE:DWebBrowserEvents2>]
+ */
+static VALUE
+foletype_default_ole_types(VALUE self)
+{
+    struct oletypedata *ptype;
+    Data_Get_Struct(self, struct oletypedata, ptype);
+    return ole_type_impl_ole_types(ptype->pTypeInfo, IMPLTYPEFLAG_FDEFAULT);
+}
+
+static VALUE
 foletype_inspect(VALUE self)
 {
     return default_inspect(self, "WIN32OLE_TYPE");
@@ -7538,7 +7599,118 @@
     return hr;
 }
 
+static HRESULT 
+find_coclass(
+    ITypeInfo *pTypeInfo, 
+    TYPEATTR *pTypeAttr, 
+    ITypeInfo **pCOTypeInfo, 
+    TYPEATTR **pCOTypeAttr)
+{
+    HRESULT hr = E_NOINTERFACE;
+    ITypeLib *pTypeLib;
+    int count;
+    BOOL found = FALSE;
+    ITypeInfo *pTypeInfo2;
+    TYPEATTR *pTypeAttr2;
+    int flags;
+    int i,j;
+    HREFTYPE href;
+    ITypeInfo *pRefTypeInfo;
+    TYPEATTR *pRefTypeAttr;
+
+    hr = pTypeInfo->lpVtbl->GetContainingTypeLib(pTypeInfo, &pTypeLib, NULL);
+    if (FAILED(hr)) {
+	return hr;
+    }
+    count = pTypeLib->lpVtbl->GetTypeInfoCount(pTypeLib);
+    for (i = 0; i < count && !found; i++) {
+	hr = pTypeLib->lpVtbl->GetTypeInfo(pTypeLib, i, &pTypeInfo2);
+	if (FAILED(hr))
+	    continue;
+	hr = OLE_GET_TYPEATTR(pTypeInfo2, &pTypeAttr2);
+	if (FAILED(hr)) {
+	    OLE_RELEASE(pTypeInfo2);
+	    continue;
+	}
+	if (pTypeAttr2->typekind != TKIND_COCLASS) {
+	    OLE_RELEASE_TYPEATTR(pTypeInfo2, pTypeAttr2);
+	    OLE_RELEASE(pTypeInfo2);
+	    continue;
+	}
+	for (j = 0; j < pTypeAttr2->cImplTypes && !found; j++) {
+	    hr = pTypeInfo2->lpVtbl->GetImplTypeFlags(pTypeInfo2, j, &flags);
+	    if (FAILED(hr))
+		continue;
+	    if (!(flags & IMPLTYPEFLAG_FDEFAULT)) 
+		continue;
+	    hr = pTypeInfo2->lpVtbl->GetRefTypeOfImplType(pTypeInfo2, j, &href);
+	    if (FAILED(hr))
+		continue;
+	    hr = pTypeInfo2->lpVtbl->GetRefTypeInfo(pTypeInfo2, href, &pRefTypeInfo);
+	    if (FAILED(hr)) 
+		continue;
+	    hr = OLE_GET_TYPEATTR(pRefTypeInfo, &pRefTypeAttr);
+	    if (FAILED(hr))  {
+		OLE_RELEASE(pRefTypeInfo);
+		continue;
+	    }
+	    if (IsEqualGUID(&(pTypeAttr->guid), &(pRefTypeAttr->guid))) {
+		found = TRUE;
+	    }
+	}
+	if (!found) {
+	    OLE_RELEASE_TYPEATTR(pTypeInfo2, pTypeAttr2);
+	    OLE_RELEASE(pTypeInfo2);
+	}
+    }
+    OLE_RELEASE(pTypeLib);
+    if (found) {
+	*pCOTypeInfo = pTypeInfo2;
+	*pCOTypeAttr = pTypeAttr2;
+	hr = S_OK;
+    } else {
+	hr = E_NOINTERFACE;
+    }
+    return hr;
+}
+
 static HRESULT
+find_default_source_from_typeinfo(
+    ITypeInfo *pTypeInfo, 
+    TYPEATTR *pTypeAttr, 
+    ITypeInfo **ppTypeInfo)
+{
+    int i = 0;
+    HRESULT hr = E_NOINTERFACE;
+    int flags;
+    HREFTYPE hRefType;
+    /* Enumerate all implemented types of the COCLASS */
+    for (i = 0; i < pTypeAttr->cImplTypes; i++) {
+        hr = pTypeInfo->lpVtbl->GetImplTypeFlags(pTypeInfo, i, &flags);
+        if (FAILED(hr))
+            continue;
+
+        /*
+           looking for the [default] [source]
+           we just hope that it is a dispinterface :-)
+        */
+        if ((flags & IMPLTYPEFLAG_FDEFAULT) &&
+            (flags & IMPLTYPEFLAG_FSOURCE)) {
+
+            hr = pTypeInfo->lpVtbl->GetRefTypeOfImplType(pTypeInfo,
+                                                         i, &hRefType);
+            if (FAILED(hr))
+                continue;
+            hr = pTypeInfo->lpVtbl->GetRefTypeInfo(pTypeInfo,
+                                                   hRefType, ppTypeInfo);
+            if (SUCCEEDED(hr))
+                break;
+        }
+    }
+    return hr;
+}
+
+static HRESULT
 find_default_source(VALUE ole, IID *piid, ITypeInfo **ppTypeInfo)
 {
     HRESULT hr;
@@ -7547,10 +7719,9 @@
 
     IDispatch *pDispatch;
     ITypeInfo *pTypeInfo;
+    ITypeInfo *pTypeInfo2 = NULL;
     TYPEATTR *pTypeAttr;
-    int i;
-    int iFlags;
-    HREFTYPE hRefType;
+    TYPEATTR *pTypeAttr2 = NULL;
 
     struct oledata *pole;
 
@@ -7564,52 +7735,45 @@
                                                  GUIDKIND_DEFAULT_SOURCE_DISP_IID,
                                                  piid);
         OLE_RELEASE(pProvideClassInfo2);
-        return find_iid(ole, NULL, piid, ppTypeInfo);
+        if (SUCCEEDED(hr)) {
+            hr = find_iid(ole, NULL, piid, ppTypeInfo);
+        }
     }
+    if (SUCCEEDED(hr)) {
+        return hr;
+    }
     hr = pDispatch->lpVtbl->QueryInterface(pDispatch,
                                            &IID_IProvideClassInfo,
                                            (void**)&pProvideClassInfo);
-    if (FAILED(hr))
-        return hr;
+    if (SUCCEEDED(hr)) {
 
-    hr = pProvideClassInfo->lpVtbl->GetClassInfo(pProvideClassInfo,
-                                                 &pTypeInfo);
-    OLE_RELEASE(pProvideClassInfo);
+        hr = pProvideClassInfo->lpVtbl->GetClassInfo(pProvideClassInfo,
+                                                     &pTypeInfo);
+        OLE_RELEASE(pProvideClassInfo);
+    }
+    if (FAILED(hr)) {
+        hr = pDispatch->lpVtbl->GetTypeInfo(pDispatch, 0, cWIN32OLE_lcid, &pTypeInfo );
+    }
     if (FAILED(hr))
         return hr;
-
     hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr);
     if (FAILED(hr)) {
         OLE_RELEASE(pTypeInfo);
         return hr;
     }
-    /* Enumerate all implemented types of the COCLASS */
-    for (i = 0; i < pTypeAttr->cImplTypes; i++) {
-        hr = pTypeInfo->lpVtbl->GetImplTypeFlags(pTypeInfo, i, &iFlags);
-        if (FAILED(hr))
-            continue;
 
-        /*
-           looking for the [default] [source]
-           we just hope that it is a dispinterface :-)
-        */
-        if ((iFlags & IMPLTYPEFLAG_FDEFAULT) &&
-            (iFlags & IMPLTYPEFLAG_FSOURCE)) {
-
-            hr = pTypeInfo->lpVtbl->GetRefTypeOfImplType(pTypeInfo,
-                                                         i, &hRefType);
-            if (FAILED(hr))
-                continue;
-            hr = pTypeInfo->lpVtbl->GetRefTypeInfo(pTypeInfo,
-                                                   hRefType, ppTypeInfo);
-            if (SUCCEEDED(hr))
-                break;
-        }
+    *ppTypeInfo = 0;
+    hr = find_default_source_from_typeinfo(pTypeInfo, pTypeAttr, ppTypeInfo);
+    if (!*ppTypeInfo) {
+	hr = find_coclass(pTypeInfo, pTypeAttr, &pTypeInfo2, &pTypeAttr2);
+	if (SUCCEEDED(hr)) {
+	    hr = find_default_source_from_typeinfo(pTypeInfo2, pTypeAttr2, ppTypeInfo);
+	    OLE_RELEASE_TYPEATTR(pTypeInfo2, pTypeAttr2);
+	    OLE_RELEASE(pTypeInfo2);
+	}
     }
-
     OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr);
     OLE_RELEASE(pTypeInfo);
-
     /* Now that would be a bad surprise, if we didn't find it, wouldn't it? */
     if (!*ppTypeInfo) {
         if (SUCCEEDED(hr))
@@ -7658,7 +7822,7 @@
     char *pitf;
     HRESULT hr;
     IID iid;
-    ITypeInfo *pTypeInfo;
+    ITypeInfo *pTypeInfo = 0;
     IDispatch *pDispatch;
     IConnectionPointContainer *pContainer;
     IConnectionPoint *pConnectionPoint;
@@ -8443,6 +8607,9 @@
     rb_define_method(cWIN32OLE_TYPE, "ole_methods", foletype_methods, 0);
     rb_define_method(cWIN32OLE_TYPE, "ole_typelib", foletype_ole_typelib, 0);
     rb_define_method(cWIN32OLE_TYPE, "implemented_ole_types", foletype_impl_ole_types, 0);
+    rb_define_method(cWIN32OLE_TYPE, "source_ole_types", foletype_source_ole_types, 0);
+    rb_define_method(cWIN32OLE_TYPE, "default_event_sources", foletype_default_event_sources, 0);
+    rb_define_method(cWIN32OLE_TYPE, "default_ole_types", foletype_default_ole_types, 0);
     rb_define_method(cWIN32OLE_TYPE, "inspect", foletype_inspect, 0);
 
     cWIN32OLE_VARIABLE = rb_define_class("WIN32OLE_VARIABLE", rb_cObject);
Index: mvm/ext/nkf/nkf-utf8/nkf.c
===================================================================
--- mvm/ext/nkf/nkf-utf8/nkf.c	(revision 17977)
+++ mvm/ext/nkf/nkf-utf8/nkf.c	(revision 17978)
@@ -6086,8 +6086,8 @@
 		    input_endian = ENDIAN_BIG;
 		}
 		enc_idx = enc_idx == UTF_16
-		    ? (output_endian == ENDIAN_LITTLE ? UTF_16LE : UTF_16BE)
-		    : (output_endian == ENDIAN_LITTLE ? UTF_32LE : UTF_32BE);
+		    ? (input_endian == ENDIAN_LITTLE ? UTF_16LE : UTF_16BE)
+		    : (input_endian == ENDIAN_LITTLE ? UTF_32LE : UTF_32BE);
 		input_encoding = nkf_enc_from_index(enc_idx);
 	    }
 	    continue;
Index: mvm/.merged-trunk-revision
===================================================================
--- mvm/.merged-trunk-revision	(revision 17977)
+++ mvm/.merged-trunk-revision	(revision 17978)
@@ -1 +1 @@
-17917
+17977
Index: mvm/vm.c
===================================================================
--- mvm/vm.c	(revision 17977)
+++ mvm/vm.c	(revision 17978)
@@ -1388,7 +1388,7 @@
 	RUBY_MARK_UNLESS_NULL(vm->load_path);
 	RUBY_MARK_UNLESS_NULL(vm->loaded_features);
 	RUBY_MARK_UNLESS_NULL(vm->top_self);
-	rb_gc_mark_locations(vm->specific_storage.ptr, vm->specific_storage.ptr + vm->specific_storage.len - 1);
+	rb_gc_mark_locations(vm->specific_storage.ptr, vm->specific_storage.ptr + vm->specific_storage.len);
 
 	if (vm->loading_table) {
 	    rb_mark_tbl(vm->loading_table);
@@ -1909,9 +1909,3 @@
 {
     return ruby_vm_debug_ptr(GET_VM());
 }
-
-VALUE
-rb_vm_get_coverages(void)
-{
-    return *rb_vm_specific_ptr(rb_vmkey_coverages);
-}
Index: mvm/version.h
===================================================================
--- mvm/version.h	(revision 17977)
+++ mvm/version.h	(revision 17978)
@@ -1,7 +1,7 @@
 #define RUBY_VERSION "1.9.0"
-#define RUBY_RELEASE_DATE "2008-07-07"
+#define RUBY_RELEASE_DATE "2008-07-09"
 #define RUBY_VERSION_CODE 190
-#define RUBY_RELEASE_CODE 20080707
+#define RUBY_RELEASE_CODE 20080709
 #define RUBY_PATCHLEVEL 0
 
 #define RUBY_VERSION_MAJOR 1
@@ -9,7 +9,7 @@
 #define RUBY_VERSION_TEENY 0
 #define RUBY_RELEASE_YEAR 2008
 #define RUBY_RELEASE_MONTH 7
-#define RUBY_RELEASE_DAY 7
+#define RUBY_RELEASE_DAY 9
 
 #ifdef RUBY_EXTERN
 RUBY_EXTERN const char ruby_version[];
Index: mvm/test/ruby/test_string.rb
===================================================================
--- mvm/test/ruby/test_string.rb	(revision 17977)
+++ mvm/test/ruby/test_string.rb	(revision 17978)
@@ -1221,7 +1221,9 @@
 
     assert_equal(S("124"),  S("123").succ)
     assert_equal(S("1000"), S("999").succ)
+    assert_equal(S("2.000"), S("1.999").succ)
 
+    assert_equal(S("No.10"), S("No.9").succ)
     assert_equal(S("2000aaa"),  S("1999zzz").succ)
     assert_equal(S("AAAAA000"), S("ZZZZ999").succ)
     assert_equal(S("*+"), S("**").succ)
@@ -1269,6 +1271,10 @@
     assert_equal(S("*+"), a.succ!)
     assert_equal(S("*+"), a)
 
+    a = S("No.9")
+    assert_equal(S("No.10"), a.succ!)
+    assert_equal(S("No.10"), a)
+
     assert_equal("aaaaaaaaaaaa", "zzzzzzzzzzz".succ!)
     assert_equal("aaaaaaaaaaaaaaaaaaaaaaaa", "zzzzzzzzzzzzzzzzzzzzzzz".succ!)
   end
Index: mvm/test/ruby/test_dir.rb
===================================================================
--- mvm/test/ruby/test_dir.rb	(revision 17977)
+++ mvm/test/ruby/test_dir.rb	(revision 17978)
@@ -131,7 +131,8 @@
   end
 
   def test_chroot_nodir
-    assert_raise(NotImplementedError, Errno::ENOENT) { Dir.chroot(File.join(@nodir, "")) }
+    assert_raise(NotImplementedError, Errno::ENOENT, Errno::EPERM
+		) { Dir.chroot(File.join(@nodir, "")) }
   end
 
   def test_close
Index: mvm/test/win32ole/test_win32ole_event.rb
===================================================================
--- mvm/test/win32ole/test_win32ole_event.rb	(revision 17977)
+++ mvm/test/win32ole/test_win32ole_event.rb	(revision 17978)
@@ -30,6 +30,20 @@
       @event += event
     end
 
+    def test_s_new_without_itf
+      ev = WIN32OLE_EVENT.new(@ie)
+      ev.on_event {|*args| default_handler(*args)}
+      @ie.navigate("file:///#{@f}")
+      while @ie.busy
+        WIN32OLE_EVENT.new(@ie)
+        GC.start  
+        WIN32OLE_EVENT.message_loop
+        sleep 0.1
+      end
+      assert_match(/BeforeNavigate/, @event)
+      assert_match(/NavigateComplete/, @event)
+    end
+
     def test_on_event
       ev = WIN32OLE_EVENT.new(@ie, 'DWebBrowserEvents')
       ev.on_event {|*args| default_handler(*args)}
@@ -111,6 +125,16 @@
       }
     end
 
+    def test_non_exist_event
+      assert_raise(RuntimeError) {
+        ev = WIN32OLE_EVENT.new(@ie, 'XXXX')
+      }
+      dict = WIN32OLE.new('Scripting.Dictionary')
+      assert_raise(RuntimeError) {
+        ev = WIN32OLE_EVENT.new(dict)
+      }
+    end
+
     def handler1
       @event2 = "handler1"
     end
Index: mvm/test/win32ole/test_win32ole_type.rb
===================================================================
--- mvm/test/win32ole/test_win32ole_type.rb	(revision 17977)
+++ mvm/test/win32ole/test_win32ole_type.rb	(revision 17978)
@@ -166,10 +166,61 @@
     def test_implemented_ole_types
       ole_types = @ole_type.implemented_ole_types
       assert_instance_of(Array, ole_types)
-      assert(ole_types.size > 0)
+      assert_equal(1, ole_types.size)
       assert_match(/^IShellDispatch5{0,1}$/, ole_types[0].name)
+
+      ie_otype = WIN32OLE_TYPE.new("Microsoft Internet Controls", "InternetExplorer")
+      ole_types = ie_otype.implemented_ole_types
+      assert_equal(4, ole_types.size)
+      otype = ole_types.select{|t| t.name == "IWebBrowser2"}
+      assert_equal(1, otype.size)
+      otype = ole_types.select{|t| t.name == "IWebBrowserApp"}
+      assert_equal(1, otype.size)
+      otype = ole_types.select{|t| t.name == "DWebBrowserEvents2"}
+      assert_equal(1, otype.size)
+      otype = ole_types.select{|t| t.name == "DWebBrowserEvents"}  
+      assert_equal(1, otype.size)
     end
 
+    def test_default_ole_types
+      ie_otype = WIN32OLE_TYPE.new("Microsoft Internet Controls", "InternetExplorer")
+      ole_types = ie_otype.default_ole_types
+      otype = ole_types.select{|t| t.name == "IWebBrowser2"}
+      assert_equal(1, otype.size)
+      otype = ole_types.select{|t| t.name == "IWebBrowserApp"}
+      assert_equal(0, otype.size)
+      otype = ole_types.select{|t| t.name == "DWebBrowserEvents2"}
+      assert_equal(1, otype.size)
+      otype = ole_types.select{|t| t.name == "DWebBrowserEvents"}  
+      assert_equal(0, otype.size)
+    end
+
+    def test_source_ole_types
+      ie_otype = WIN32OLE_TYPE.new("Microsoft Internet Controls", "InternetExplorer")
+      ole_types = ie_otype.source_ole_types
+      otype = ole_types.select{|t| t.name == "IWebBrowser2"}
+      assert_equal(0, otype.size)
+      otype = ole_types.select{|t| t.name == "IWebBrowserApp"}
+      assert_equal(0, otype.size)
+      otype = ole_types.select{|t| t.name == "DWebBrowserEvents2"}
+      assert_equal(1, otype.size)
+      otype = ole_types.select{|t| t.name == "DWebBrowserEvents"}  
+      assert_equal(1, otype.size)
+    end
+
+    def test_default_event_sources
+      ie_otype = WIN32OLE_TYPE.new("Microsoft Internet Controls", "InternetExplorer")
+      ole_types = ie_otype.default_event_sources
+      otype = ole_types.select{|t| t.name == "IWebBrowser2"}
+      assert_equal(0, otype.size)
+      otype = ole_types.select{|t| t.name == "IWebBrowserApp"}
+      assert_equal(0, otype.size)
+      otype = ole_types.select{|t| t.name == "DWebBrowserEvents2"}
+      assert_equal(1, otype.size)
+      otype = ole_types.select{|t| t.name == "DWebBrowserEvents"}  
+      assert_equal(0, otype.size)
+    end
+
     def test_inspect
       assert_equal("#<WIN32OLE_TYPE:Shell>", @ole_type.inspect)
     end

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

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