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/