ruby-changes:6427
From: usa <ko1@a...>
Date: Mon, 7 Jul 2008 23:54:11 +0900 (JST)
Subject: [ruby-changes:6427] Ruby:r17943 (win32-unicode-test): * pullup r17942.
usa 2008-07-07 23:53:22 +0900 (Mon, 07 Jul 2008) New Revision: 17943 Added directories: branches/win32-unicode-test/ext/coverage/ Added files: branches/win32-unicode-test/test/test_singleton.rb Modified files: branches/win32-unicode-test/ChangeLog branches/win32-unicode-test/Makefile.in branches/win32-unicode-test/configure.in branches/win32-unicode-test/encoding.c branches/win32-unicode-test/eval.c branches/win32-unicode-test/ext/bigdecimal/bigdecimal.c branches/win32-unicode-test/ext/json/ext/generator/generator.c branches/win32-unicode-test/ext/socket/socket.c branches/win32-unicode-test/ext/win32ole/win32ole.c branches/win32-unicode-test/file.c branches/win32-unicode-test/gc.c branches/win32-unicode-test/include/ruby/encoding.h branches/win32-unicode-test/include/ruby/intern.h branches/win32-unicode-test/include/ruby/oniguruma.h branches/win32-unicode-test/include/ruby/ruby.h branches/win32-unicode-test/insns.def branches/win32-unicode-test/io.c branches/win32-unicode-test/iseq.c branches/win32-unicode-test/lib/coverage.rb branches/win32-unicode-test/lib/ipaddr.rb branches/win32-unicode-test/lib/net/ftp.rb branches/win32-unicode-test/lib/net/smtp.rb branches/win32-unicode-test/lib/test/unit/autorunner.rb branches/win32-unicode-test/lib/test/unit/collector/dir.rb branches/win32-unicode-test/lib/test/unit/collector/objectspace.rb branches/win32-unicode-test/lib/test/unit/testcase.rb branches/win32-unicode-test/missing/tgamma.c branches/win32-unicode-test/numeric.c branches/win32-unicode-test/parse.y branches/win32-unicode-test/proc.c branches/win32-unicode-test/process.c branches/win32-unicode-test/rational.c branches/win32-unicode-test/re.c branches/win32-unicode-test/regint.h branches/win32-unicode-test/sprintf.c branches/win32-unicode-test/test/ruby/test_dir.rb branches/win32-unicode-test/test/ruby/test_m17n.rb branches/win32-unicode-test/test/ruby/test_m17n_comb.rb branches/win32-unicode-test/test/win32ole/test_win32ole.rb branches/win32-unicode-test/test/win32ole/test_win32ole_type.rb branches/win32-unicode-test/test/win32ole/test_win32ole_variant.rb branches/win32-unicode-test/test/win32ole/test_word.rb branches/win32-unicode-test/thread.c branches/win32-unicode-test/thread_pthread.c branches/win32-unicode-test/thread_win32.c branches/win32-unicode-test/version.h branches/win32-unicode-test/vm.c branches/win32-unicode-test/vm_core.h branches/win32-unicode-test/win32/win32.c Log: * pullup r17942. Added: branches/win32-unicode-test/ext/coverage/ http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=17943 Index: win32-unicode-test/encoding.c =================================================================== --- win32-unicode-test/encoding.c (revision 17942) +++ win32-unicode-test/encoding.c (revision 17943) @@ -19,10 +19,12 @@ static ID id_encoding, id_base_encoding; VALUE rb_cEncoding; +static VALUE rb_encoding_list; struct rb_encoding_entry { const char *name; rb_encoding *enc; + rb_encoding *base; }; static struct { @@ -49,36 +51,60 @@ static VALUE enc_new(rb_encoding *encoding) { - VALUE enc = Data_Wrap_Struct(rb_cEncoding, enc_mark, 0, encoding); - encoding->auxiliary_data = (void *)enc; - return enc; + return Data_Wrap_Struct(rb_cEncoding, enc_mark, 0, encoding); } VALUE rb_enc_from_encoding(rb_encoding *encoding) { + VALUE list, enc; + int idx; + if (!encoding) return Qnil; - if (enc_initialized_p(encoding)) - return ENC_FROM_ENCODING(encoding); - return enc_new(encoding); + idx = ENC_TO_ENCINDEX(encoding); + if (!(list = rb_encoding_list)) { + rb_bug("rb_enc_from_encoding(%d\"%s\"): no rb_encoding_list", + idx, rb_enc_name(encoding)); + } + enc = rb_ary_entry(list, idx); + if (NIL_P(enc)) { + rb_bug("rb_enc_from_encoding(%d\"%s\"): not created yet", + idx, rb_enc_name(encoding)); + } + return enc; } +static int enc_autoload(rb_encoding *); + static int -enc_check_encoding(VALUE obj) +check_encoding(rb_encoding *enc) { - int index; - rb_encoding *enc; + int index = rb_enc_to_index(enc); + if (rb_enc_from_index(index) != enc) + return -1; + if (enc_autoload_p(enc)) { + index = enc_autoload(enc); + } + return index; +} +static int +enc_check_encoding(VALUE obj) +{ if (SPECIAL_CONST_P(obj) || BUILTIN_TYPE(obj) != T_DATA || RDATA(obj)->dmark != enc_mark) { return -1; } - enc = (rb_encoding*)RDATA(obj)->data; - index = rb_enc_to_index(enc); - if (rb_enc_from_index(index) != enc) - return -1; - if (enc_autoload_p(enc)) { - index = rb_enc_find_index(enc->name); + return check_encoding(RDATA(obj)->data); +} + +static int +must_encoding(VALUE enc) +{ + int index = enc_check_encoding(enc); + if (index < 0) { + rb_raise(rb_eTypeError, "wrong argument type %s (expected Encoding)", + rb_obj_classname(enc)); } return index; } @@ -116,13 +142,6 @@ void rb_gc_mark_encodings(void) { - int i; - for (i = 0; i < enc_table.count; ++i) { - rb_encoding *enc = enc_table.list[i].enc; - if (enc && enc_initialized_p(enc)) { - rb_gc_mark(ENC_FROM_ENCODING(enc)); - } - } } static int @@ -145,7 +164,7 @@ enc_register_at(int index, const char *name, rb_encoding *encoding) { struct rb_encoding_entry *ent = &enc_table.list[index]; - void *obj = ENC_UNINITIALIZED; + VALUE list; if (!ent->name) { ent->name = name = strdup(name); @@ -156,9 +175,6 @@ if (!ent->enc) { ent->enc = xmalloc(sizeof(rb_encoding)); } - else { - obj = ent->enc->auxiliary_data; - } if (encoding) { *ent->enc = *encoding; } @@ -169,16 +185,11 @@ encoding->name = name; encoding->ruby_encoding_index = index; st_insert(enc_table.names, (st_data_t)name, (st_data_t)index); - if (obj != ENC_UNINITIALIZED) { - encoding->auxiliary_data = obj; - } - else if (rb_cEncoding) { + list = rb_encoding_list; + if (list && NIL_P(rb_ary_entry(list, index))) { /* initialize encoding data */ - enc_new(encoding); + rb_ary_store(list, index, enc_new(encoding)); } - else { - encoding->auxiliary_data = ENC_UNINITIALIZED; - } return index; } @@ -205,9 +216,7 @@ if (STRCASECMP(name, rb_enc_name(oldenc))) { index = enc_register(name, encoding); } - else if (!enc_autoload_p(oldenc) || - (enc_initialized_p(oldenc) && - !ENC_DUMMY_P(ENC_FROM_ENCODING(oldenc)))) { + else if (enc_autoload_p(oldenc) || !ENC_DUMMY_P(oldenc)) { enc_register_at(index, name, encoding); } else { @@ -239,12 +248,12 @@ } } -static VALUE +static rb_encoding* set_base_encoding(int index, rb_encoding *base) { - VALUE enc = rb_enc_from_encoding(enc_table.list[index].enc); + rb_encoding *enc = enc_table.list[index].enc; - rb_ivar_set(enc, id_base_encoding, rb_enc_from_encoding(base)); + enc_table.list[index].base = base; if (rb_enc_dummy_p(base)) ENC_SET_DUMMY(enc); return enc; } @@ -293,7 +302,7 @@ rb_define_dummy_encoding(const char *name) { int index = rb_enc_replicate(name, rb_ascii8bit_encoding()); - VALUE enc = rb_enc_from_encoding(enc_table.list[index].enc); + rb_encoding *enc = enc_table.list[index].enc; ENC_SET_DUMMY(enc); return index; @@ -304,7 +313,7 @@ { int index = enc_replicate(rb_enc_registered(name), name, rb_ascii8bit_encoding()); - VALUE enc = rb_enc_from_encoding(enc_table.list[index].enc); + rb_encoding *enc = enc_table.list[index].enc; ENC_SET_DUMMY(enc); return index; @@ -326,7 +335,7 @@ static VALUE enc_dummy_p(VALUE enc) { - return ENC_DUMMY_P(enc) ? Qtrue : Qfalse; + return ENC_DUMMY_P(enc_table.list[must_encoding(enc)].enc) ? Qtrue : Qfalse; } static int @@ -448,33 +457,44 @@ return idx; } +static int +enc_autoload(rb_encoding *enc) +{ + int i; + rb_encoding *base = enc_table.list[ENC_TO_ENCINDEX(enc)].base; + + if (base) { + i = 0; + do { + if (i >= enc_table.count) return -1; + } while (enc_table.list[i].enc != base && (++i, 1)); + if (enc_autoload_p(base)) { + if (enc_autoload(base) < 0) return -1; + } + i = ENC_TO_ENCINDEX(enc); + enc_register_at(i, rb_enc_name(enc), base); + } + else { + i = load_encoding(rb_enc_name(enc)); + } + return i; +} + int rb_enc_find_index(const char *name) { - int i = rb_enc_registered(name), b; + int i = rb_enc_registered(name); rb_encoding *enc; - VALUE base; if (i < 0) { i = load_encoding(name); } else if (enc_autoload_p(enc = rb_enc_from_index(i))) { - if (enc_initialized_p(enc) && - (base = enc_base_encoding(ENC_FROM_ENCODING(enc)), !NIL_P(base))) { - if ((b = enc_check_encoding(base)) < 0) { - goto failed; - } - enc_register_at(i, rb_enc_name(enc), rb_enc_from_index(b)); + if (enc_autoload(enc) < 0) { + rb_warn("failed to load encoding (%s); use ASCII-8BIT instead", + name); + return 0; } - else { - i = load_encoding(rb_enc_name(enc)); - if (i < 0) { - failed: - rb_warn("failed to load encoding (%s); use ASCII-8BIT instead", - name); - return 0; - } - } } return i; } @@ -503,33 +523,6 @@ } } -#if 0 -static void -enc_check_capable(VALUE x) -{ - if (!enc_capable(x)) { - const char *etype; - - if (NIL_P(x)) { - etype = "nil"; - } - else if (FIXNUM_P(x)) { - etype = "Fixnum"; - } - else if (SYMBOL_P(x)) { - etype = "Symbol"; - } - else if (rb_special_const_p(x)) { - etype = RSTRING_PTR(rb_obj_as_string(x)); - } - else { - etype = rb_obj_classname(x); - } - rb_raise(rb_eTypeError, "wrong argument type %s (not encode capable)", etype); - } -} -#endif - ID rb_id_encoding(void) { @@ -777,7 +770,7 @@ { VALUE str = rb_sprintf("#<%s:%s%s>", rb_obj_classname(self), rb_enc_name((rb_encoding*)DATA_PTR(self)), - (ENC_DUMMY_P(self) ? " (dummy)" : "")); + (enc_dummy_p(self) ? " (dummy)" : "")); ENCODING_CODERANGE_SET(str, rb_usascii_encindex(), ENC_CODERANGE_7BIT); return str; } @@ -799,7 +792,9 @@ static VALUE enc_base_encoding(VALUE self) { - return rb_attr_get(self, id_base_encoding); + rb_encoding *base = enc_table.list[must_encoding(self)].base; + if (!base) return Qnil; + return ENC_FROM_ENCODING(base); } /* @@ -823,14 +818,8 @@ static VALUE enc_list(VALUE klass) { - VALUE ary = rb_ary_new2(enc_table.count); - int i; - for (i = 0; i < enc_table.count; ++i) { - rb_encoding *enc = enc_table.list[i].enc; - if (enc) { - rb_ary_push(ary, rb_enc_from_encoding(enc)); - } - } + VALUE ary = rb_ary_new2(0); + rb_ary_replace(ary, rb_encoding_list); return ary; } @@ -1183,6 +1172,8 @@ Init_Encoding(void) { #undef rb_intern + VALUE list; + int i; id_base_encoding = rb_intern("#base_encoding"); @@ -1204,6 +1195,14 @@ rb_define_singleton_method(rb_cEncoding, "default_external", get_default_external, 0); rb_define_singleton_method(rb_cEncoding, "locale_charmap", rb_locale_charmap, 0); + + rb_gc_register_address(&rb_encoding_list); + list = rb_ary_new2(enc_table.count); + RBASIC(list)->klass = 0; + rb_encoding_list = list; + for (i = 0; i < enc_table.count; ++i) { + rb_ary_push(list, enc_new(enc_table.list[i].enc)); + } } /* locale insensitive functions */ Index: win32-unicode-test/thread_win32.c =================================================================== --- win32-unicode-test/thread_win32.c (revision 17942) +++ win32-unicode-test/thread_win32.c (revision 17943) @@ -537,8 +537,6 @@ w32_set_event(th->native_thread_data.interrupt_event); } -static void timer_thread_function(void); - static HANDLE timer_thread_id = 0; static unsigned long _stdcall @@ -547,7 +545,7 @@ thread_debug("timer_thread\n"); while (system_working) { Sleep(WIN32_WAIT_TIMEOUT); - timer_thread_function(); + timer_thread_function(dummy); } thread_debug("timer killed\n"); return 0; @@ -557,7 +555,7 @@ rb_thread_create_timer_thread(void) { if (timer_thread_id == 0) { - timer_thread_id = w32_create_thread(1024, timer_thread_func, 0); + timer_thread_id = w32_create_thread(1024, timer_thread_func, GET_VM()); w32_resume_thread(timer_thread_id); } } Index: win32-unicode-test/include/ruby/intern.h =================================================================== --- win32-unicode-test/include/ruby/intern.h (revision 17942) +++ win32-unicode-test/include/ruby/intern.h (revision 17943) @@ -386,6 +386,7 @@ void rb_write_error2(const char*, long); int rb_io_mode_modenum(const char *mode); void rb_close_before_exec(int lowfd, int maxhint, VALUE noclose_fds); +int rb_pipe(int *pipes); /* marshal.c */ VALUE rb_marshal_dump(VALUE, VALUE); VALUE rb_marshal_load(VALUE); Index: win32-unicode-test/include/ruby/ruby.h =================================================================== --- win32-unicode-test/include/ruby/ruby.h (revision 17942) +++ win32-unicode-test/include/ruby/ruby.h (revision 17943) @@ -357,13 +357,13 @@ #define NUM2ULONG(x) rb_num2ulong((VALUE)x) #if SIZEOF_INT < SIZEOF_LONG long rb_num2int(VALUE); -#define NUM2INT(x) (FIXNUM_P(x)?FIX2INT(x):rb_num2int((VALUE)x)) +#define NUM2INT(x) ((int)(FIXNUM_P(x)?FIX2INT(x):rb_num2int((VALUE)x))) long rb_fix2int(VALUE); -#define FIX2INT(x) rb_fix2int((VALUE)x) +#define FIX2INT(x) ((int)rb_fix2int((VALUE)x)) unsigned long rb_num2uint(VALUE); -#define NUM2UINT(x) rb_num2uint(x) +#define NUM2UINT(x) ((unsigned int)rb_num2uint(x)) unsigned long rb_fix2uint(VALUE); -#define FIX2UINT(x) rb_fix2uint(x) +#define FIX2UINT(x) ((unsigned int)rb_fix2uint(x)) #else #define NUM2INT(x) ((int)NUM2LONG(x)) #define NUM2UINT(x) ((unsigned int)NUM2ULONG(x)) Index: win32-unicode-test/include/ruby/encoding.h =================================================================== --- win32-unicode-test/include/ruby/encoding.h (revision 17942) +++ win32-unicode-test/include/ruby/encoding.h (revision 17943) @@ -70,7 +70,7 @@ int rb_enc_replicate(const char *, rb_encoding *); int rb_define_dummy_encoding(const char *); -#define rb_enc_to_index(enc) ((enc) ? ((enc)->ruby_encoding_index) : 0) +#define rb_enc_to_index(enc) ((enc) ? ENC_TO_ENCINDEX(enc) : 0) int rb_enc_get_index(VALUE obj); void rb_enc_set_index(VALUE obj, int encindex); int rb_enc_find_index(const char *name); @@ -176,20 +176,21 @@ long rb_memsearch(const void*,long,const void*,long,rb_encoding*); RUBY_EXTERN VALUE rb_cEncoding; +#define enc_initialized_p(enc) ((enc)->ruby_encoding_index != ENC_UNINITIALIZED) +#define ENC_DUMMY_FLAG (1<<24) +#define ENC_INDEX_MASK (~(~0U<<24)) -#define ENC_UNINITIALIZED (&rb_cEncoding) -#define enc_initialized_p(enc) ((enc)->auxiliary_data != &rb_cEncoding) -#define ENC_FROM_ENCODING(enc) ((VALUE)(enc)->auxiliary_data) +#define ENC_TO_ENCINDEX(enc) ((enc)->ruby_encoding_index & ENC_INDEX_MASK) +#define ENC_FROM_ENCINDEX(idx) (RARRAY_PTR(rb_encoding_list)[idx]) +#define ENC_FROM_ENCODING(enc) ENC_FROM_ENCINDEX(ENC_TO_ENCINDEX(enc)) -#define ENC_DUMMY_FLAG FL_USER2 -#define ENC_DUMMY_P(enc) (RBASIC(enc)->flags & ENC_DUMMY_FLAG) -#define ENC_SET_DUMMY(enc) (RBASIC(enc)->flags |= ENC_DUMMY_FLAG) +#define ENC_DUMMY_P(enc) ((enc)->ruby_encoding_index & ENC_DUMMY_FLAG) +#define ENC_SET_DUMMY(enc) ((enc)->ruby_encoding_index |= ENC_DUMMY_FLAG) static inline int rb_enc_dummy_p(rb_encoding *enc) { - if (!enc_initialized_p(enc)) return Qfalse; - return ENC_DUMMY_P(ENC_FROM_ENCODING(enc)); + return ENC_DUMMY_P(enc) != 0; } int rb_transcode_convertible(const char* from_encoding, const char* to_encoding); Index: win32-unicode-test/include/ruby/oniguruma.h =================================================================== --- win32-unicode-test/include/ruby/oniguruma.h (revision 17942) +++ win32-unicode-test/include/ruby/oniguruma.h (revision 17943) @@ -166,7 +166,6 @@ int (*get_ctype_code_range)(OnigCtype ctype, OnigCodePoint* sb_out, const OnigCodePoint* ranges[], struct OnigEncodingTypeST* enc); OnigUChar* (*left_adjust_char_head)(const OnigUChar* start, const OnigUChar* p, struct OnigEncodingTypeST* enc); int (*is_allowed_reverse_match)(const OnigUChar* p, const OnigUChar* end, struct OnigEncodingTypeST* enc); - void *auxiliary_data; int ruby_encoding_index; } OnigEncodingType; Index: win32-unicode-test/configure.in =================================================================== --- win32-unicode-test/configure.in (revision 17942) +++ win32-unicode-test/configure.in (revision 17943) @@ -700,6 +700,27 @@ ;; esac AC_FUNC_MEMCMP + +# http://sources.redhat.com/ml/libc-hacker/2005-08/msg00008.html +# Debian GNU/Linux Etch's libc6.1 2.3.6.ds1-13etch5 has this problem. +# Debian GNU/Linux Lenny's libc6.1 2.7-10 has no problem. +AC_CACHE_CHECK(for broken erfc of glibc-2.3.6 on IA64, rb_broken_glibc_ia64_erfc, + [AC_TRY_RUN([ +#include <math.h> +int +main() +{ + erfc(10000.0); + return 0; +} +], + rb_broken_glibc_ia64_erfc=no, + rb_broken_glibc_ia64_erfc=yes, + rb_broken_glibc_ia64_erfc=no)]) +case $rb_broken_glibc_ia64_erfc in + yes) ac_cv_func_erf=no;; +esac + AC_REPLACE_FUNCS(dup2 memmove strerror strftime\ strchr strstr crypt flock vsnprintf\ isnan finite isinf hypot acosh erf tgamma lgamma_r cbrt \ Index: win32-unicode-test/re.c =================================================================== --- win32-unicode-test/re.c (revision 17942) +++ win32-unicode-test/re.c (revision 17943) @@ -2085,7 +2085,8 @@ static int unescape_nonascii(const char *p, const char *end, rb_encoding *enc, - VALUE buf, rb_encoding **encp, onig_errmsg_buffer err) + VALUE buf, rb_encoding **encp, int *has_property, + onig_errmsg_buffer err) { char c; char smallbuf[2]; @@ -2163,6 +2164,12 @@ break; } + case 'p': /* \p{Hiragana} */ + if (!*encp) { + *has_property = 1; + } + goto escape_asis; + default: /* \n, \\, \d, \9, etc. */ escape_asis: smallbuf[0] = '\\'; @@ -2186,6 +2193,7 @@ rb_encoding **fixed_enc, onig_errmsg_buffer err) { VALUE buf; + int has_property = 0; buf = rb_str_buf_new(0); @@ -2196,9 +2204,13 @@ rb_enc_associate(buf, enc); } - if (unescape_nonascii(p, end, enc, buf, fixed_enc, err) != 0) + if (unescape_nonascii(p, end, enc, buf, fixed_enc, &has_property, err) != 0) return Qnil; + if (has_property && !*fixed_enc) { + *fixed_enc = enc; + } + if (*fixed_enc) { rb_enc_associate(buf, *fixed_enc); } Index: win32-unicode-test/insns.def =================================================================== --- win32-unicode-test/insns.def (revision 17942) +++ win32-unicode-test/insns.def (revision 17943) @@ -853,23 +853,7 @@ { rb_event_flag_t flag = nf; - if (flag == RUBY_EVENT_COVERAGE) { - VALUE coverage = GET_ISEQ()->coverage; - if (coverage) { - long line = vm_get_sourceline(GET_CFP()) - 1; - long count; - if (RARRAY_PTR(coverage)[line] == Qnil) { - rb_bug("bug"); - } - count = FIX2LONG(RARRAY_PTR(coverage)[line]) + 1; - if (POSFIXABLE(count)) { - RARRAY_PTR(coverage)[line] = LONG2FIX(count); - } - } - } - else { - EXEC_EVENT_HOOK(th, flag, GET_SELF(), 0, 0 /* TODO: id, klass */); - } + EXEC_EVENT_HOOK(th, flag, GET_SELF(), 0, 0 /* TODO: id, klass */); } /**********************************************************/ Index: win32-unicode-test/ChangeLog =================================================================== --- win32-unicode-test/ChangeLog (revision 17942) +++ win32-unicode-test/ChangeLog (revision 17943) @@ -1,3 +1,263 @@ +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 + IPAddr#to_range. a patch from okkez <okkez000 AT gmail.com> in + [ruby-dev:35091]. + +Mon Jul 7 01:24:43 2008 Nobuyoshi Nakada <nobu@r...> + + * file.c (rb_file_s_extname): fix for file name with spaces. + [ruby-talk:307404] + +Mon Jul 7 00:59:37 2008 Nobuyoshi Nakada <nobu@r...> + + * thread_pthread.c (ruby_init_stack): prior STACK_END_ADDRESS if + found. [ruby-core:17624] + +Sun Jul 6 23:48:06 2008 Nobuyoshi Nakada <nobu@r...> + + * ext/socket/socket.c (bsock_send, s_recvfrom, ruby_connect, s_accept), + (udp_send, unix_send_io, unix_recv_io): blocking region support. + +Sun Jul 6 18:34:35 2008 Masaki Suketa <masaki.suketa@n...> + + * test/win32ole/test_win32ole_type.rb (test_initialize): add + more assertions. + +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. + +Sun Jul 6 00:56:51 2008 Tanaka Akira <akr@f...> + + * ext/socket/socket.c (host_str): fix type mismatch in rb_raise + format and argument. + (port_str): ditto. + (unix_recv_io): ditto. + (sock_s_unpack_sockaddr_un): ditto. + +Sat Jul 5 23:42:23 2008 Tanaka Akira <akr@f...> + + * include/ruby/ruby.h (NUM2INT): cast to int. + (FIX2INT): ditto. + (NUM2UINT): cast to unsigned int. + (FIX2UINT): ditto. + +Sat Jul 5 23:10:41 2008 Tanaka Akira <akr@f...> + + * io.c (rb_pipe): new function for handling EMFILE and ENFILE + error of pipe(). + (UPDATE_MAXFD_PIPE): removed. + (pipe_open): use rb_pipe. + (rb_io_s_pipe): ditto. + + * process.c (pipe_nocrash): use rb_pipe. + + * include/ruby/intern.h (rb_pipe): declared. + +Sat Jul 5 22:22:27 2008 Nobuyoshi Nakada <nobu@r...> + + * thread.c (thread_initialize): NUM2INT() returns int. + + * thread.c (timer_thread_function), thread_pthread.c (thread_timer), + thread_win32.c (timer_thread_func), thread_{pthread,win32}.c + (rb_thread_create_timer_thread): passing VM. + +Sat Jul 5 20:53:18 2008 Masaki Suketa <masaki.suketa@n...> + + * test/win32ole/test_word.rb: check word installed. + +Sat Jul 5 16:12:54 2008 Narihiro Nakamura <authorNari@g...> + + * gc.c: revert. before lazy sweep. + +Sat Jul 5 09:55:44 2008 Masaki Suketa <masaki.suketa@n...> + + * ext/win32ole/win32ole.c: add WIN32OLE#ole_respond_to? + + * test/win32ole/test_win32ole.rb: ditto. + +Sat Jul 5 08:48:05 2008 Tanaka Akira <akr@f...> + + * re.c (unescape_nonascii): add has_property argument not to + raise error by /\p{Hiragana}\u{3042}/ in EUC-JP script. + (rb_reg_preprocess): use has_property argument to make regexp + encoding fixed. + +Sat Jul 5 08:29:47 2008 Tanaka Akira <akr@f...> + + * re.c (unescape_nonascii): make regexp fixed_encoding if \p is used. + fixed [ruby-core:17279]. + +Fri Jul 4 23:12:53 2008 Masaki Suketa <masaki.suketa@n...> + + * ext/win32ole/win32ole.c (d2time): fix the bug of VT_DATE + to String conversion when negative value. + + * test/win32ole/test_win32ole_variant.rb: ditto. + +Fri Jul 4 22:15:29 2008 Tanaka Akira <akr@f...> + + * lib/test/unit/testcase.rb: collect decendants of + Test::Unit::TestCase using inherited. + + * lib/test/unit/autorunner.rb: don't use ObjectSpace.each_object. + + * lib/test/unit/collector/dir.rb: ditto. + + * lib/test/unit/collector/objectspace.rb: ditto. + + [ruby-core:17126] + +Fri Jul 4 20:43:53 2008 Nobuyoshi Nakada <nobu@r...> + + * include/ruby/oniguruma.h (OnigEncoding): removed auxiliary_data. + + * include/ruby/encoding.h (ENC_DUMMY_P): moved dummy encoding flag to + rb_encoding from Encoding instance. + + * encoding.c (rb_encoding_list): list of Encoding instances. + + * encoding.c (struct rb_encoding_entry): moved base encoding from + instance variable. + +Fri Jul 4 17:51:07 2008 NAKAMURA Usaku <usa@r...> + + * numeric.c (check_uint, rb_num2uint, rb_fix2uint): proper check. + +Fri Jul 4 14:17:22 2008 Nobuyoshi Nakada <nobu@r...> + + * lib/net/ftp.rb (Net::FTP#sendport): use divmod. [ruby-core:17557] + +Fri Jul 4 11:08:37 2008 Narihiro Nakamura <authorNari@g...> + + * gc.c (garbage_collect_force): sweep is completely ended. + + * gc.c (os_obj_of): invoke garbage_collect_force() when freelist none. + +Fri Jul 4 05:01:26 2008 NAKAMURA Usaku <usa@r...> + + * numeric.c (rb_num2uint, rb_fix2uint): typo. + +Fri Jul 4 02:21:06 2008 NAKAMURA Usaku <usa@r...> + + * numeric.c (check_uint, rb_num2uint, rb_fix2uint): also needs checking + negative value. see [ruby-dev:33683] + +Thu Jul 3 23:26:36 2008 Yusuke Endoh <mame@t...> + + * include/ruby/intern.h: remove prototypes about coverage. + + * iseq.c (prepare_iseq_build): add prototype. + + * parse.y (coverage): ditto. + + * thread.c (clear_coverage): ditto. + + * thread.c (update_coverage): use rb_sourceline. + + * thread.c (rb_get_coverages): rename and move to vm.c. + + * vm.c (rb_vm_get_coverages): ditto. + + * ext/coverage/coverage.c: add rdoc. + +Thu Jul 3 21:51:21 2008 Yusuke Endoh <mame@t...> + + * ext/coverage/coverage.c, ext/coverage/extconf.rb: eliminate + COVERAGE__ and introduce coverage.so instead. How to measure + coverage: (1) require "coverage.so", (2) require or load Ruby source + file, and (3) Coverage.result will return the same hash as COVERAGE__. + [ruby-dev:35324] + + * thread.c (rb_enable_coverages): start coverage measurement by using + rb_add_event_hook. + + * thread.c (rb_get_coverages): returns current results of coverage + measurement. + + * include/ruby/intern.h: add prototype for above two functions. + + * vm_core.h, vm.c: add field of coverages to rb_vm_t. + + * insns.def (trace): remove special handling for COVERAGE__. + + * iseq.c (prepare_iseq_build): switch COVERAGE__ to + rb_get_coverages(). + + * parse.y (coverage): ditto. + + * thread.c (clear_coverage): ditto. + + * lib/coverage.rb: use coverage.so instead of COVERAGE__. + +Thu Jul 3 21:20:45 2008 Yusuke Endoh <mame@t...> + + * thread.c (thread_initialize): NUM2INT returns long. + +Thu Jul 3 21:06:16 2008 Nobuyoshi Nakada <nobu@r...> + + * eval.c (Init_eval): typo fixed in r17833. + +Thu Jul 3 19:44:44 2008 Masaki Suketa <masaki.suketa@n...> + + * ext/win32ole/win32ole.c (Init_win32ole): remove duplicate line. + +Thu Jul 3 16:08:36 2008 Tanaka Akira <akr@f...> + + * configure.in (erfc): erfc of glibc comes with Debian GNU/Linux Etch + on IA64 is broken. erfc(10000.0) aborts. + use missing/erf.c instead. + http://sources.redhat.com/ml/libc-hacker/2005-08/msg00008.html + +Thu Jul 3 12:49:39 2008 Yukihiro Matsumoto <matz@r...> + + * lib/net/smtp.rb (Net::SMTP::start): use 'localhost' instead of + 'localhost.localdomain'. [ruby-dev:35333] + + * lib/net/smtp.rb (Net::SMTP::SMTP.start): ditto. + +Thu Jul 3 07:06:02 2008 Nobuyoshi Nakada <nobu@r...> + + * Makefile.in (SET_LC_MESSAGES): LC_MESSAGES must be C. + +Thu Jul 3 07:02:55 2008 Nobuyoshi Nakada <nobu@r...> + + * eval.c (Init_eval), gc.c (Init_GC), proc.c (Init_Proc): freeze + messages of preallocated special exceptions also. + +Thu Jul 3 04:39:30 2008 Nobuyoshi Nakada <nobu@r...> + + * gc.c (rb_during_gc): VALUE cache is irrelevant. + +Thu Jul 3 01:44:01 2008 Yusuke Endoh <mame@t...> + + * regint.h (GET_ALIGNMENT_PAD_SIZE, ALIGNMENT_RIGHT): cast pointer to + uintptr_t instead of unsigned int. + +Thu Jul 3 01:23:13 2008 Yusuke Endoh <mame@t...> + + * sprintf.c: include ieeefp.h to refer isinf. + + * ext/bigdecimal/bigdecimal.c: ditto. + + * ext/json/ext/generator/generator.c: ditto. + + * rational.c: ditto. + Thu Jul 3 01:19:00 2008 NARUSE, Yui <naruse@r...> * win32/win32.c (rb_w32_write_console): this function converts output characters @@ -12,6 +272,10 @@ * include/ruby/encoding.h (rb_transcode_convertible): ditto. +Thu Jul 3 01:01:57 2008 Yusuke Endoh <mame@t...> + + * missing/tgamma.c (tgamma): remove unused variable. + Thu Jul 3 00:18:00 2008 Masaki Suketa <masaki.suketa@n...> * ext/win32ole/win32ole.c: avoid creating Ruby object during @@ -27,11 +291,15 @@ * include/ruby/intern.h: ditto. Wed Jul 2 09:49:10 2008 Narihiro Nakamura <authorNari@g...> - - * gc.c (gc_lazy_sweep) : use lazy sweep algorithm for response performance gain. - (garbage_collect_force) : mark and lazysweep invoke, after erasing all mark. - (GC_NOT_LAZY_SWEEP) : not lazy sweep flag. for debug. + * gc.c (gc_lazy_sweep) : use lazy sweep algorithm for response + performance gain. + + * gc.c (garbage_collect_force) : mark and lazysweep invoke, after + erasing all mark. + + * gc.c (GC_NOT_LAZY_SWEEP) : not lazy sweep flag. for debug. + Wed Jul 2 03:42:44 2008 Yusuke Endoh <mame@t...> * test/ruby/test_settracefunc.rb: fix expected traces for Index: win32-unicode-test/thread_pthread.c =================================================================== --- win32-unicode-test/thread_pthread.c (revision 17942) +++ win32-unicode-test/thread_pthread.c (revision 17943) @@ -179,6 +179,10 @@ #endif } native_main_thread; +#ifdef STACK_END_ADDRESS +extern void *STACK_END_ADDRESS; +#endif + #undef ruby_init_stack void ruby_init_stack(VALUE *addr @@ -188,12 +192,16 @@ ) { native_main_thread.id = pthread_self(); +#ifdef STACK_END_ADDRESS + native_main_thread.stack_start = STACK_END_ADDRESS; +#else if (!native_main_thread.stack_start || STACK_UPPER(&addr, native_main_thread.stack_start > addr, native_main_thread.stack_start < addr)) { native_main_thread.stack_start = addr; } +#endif #ifdef __ia64 if (!native_main_thread.register_stack_start || (VALUE*)bsp < native_main_thread.register_stack_start) { @@ -641,7 +649,6 @@ } static pthread_t timer_thread_id; -static void timer_thread_function(void); static void * thread_timer(void *dummy) @@ -670,7 +677,7 @@ }); } #endif - timer_thread_function(); + timer_thread_function(dummy); } return NULL; } @@ -688,7 +695,7 @@ #ifdef PTHREAD_STACK_MIN pthread_attr_setstacksize(&attr, PTHREAD_STACK_MIN); #endif - err = pthread_create(&timer_thread_id, &attr, thread_timer, 0); + err = pthread_create(&timer_thread_id, &attr, thread_timer, GET_VM()); if (err != 0) { rb_bug("rb_thread_create_timer_thread: return non-zero (%d)", err); } Index: win32-unicode-test/vm_core.h =================================================================== --- win32-unicode-test/vm_core.h (revision 17942) +++ win32-unicode-test/vm_core.h (revision 17943) @@ -333,6 +333,7 @@ int src_encoding_index; VALUE verbose, debug, progname; + VALUE coverages; #if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE struct rb_objspace *objspace; Index: win32-unicode-test/iseq.c =================================================================== --- win32-unicode-test/iseq.c (revision 17942) +++ win32-unicode-test/iseq.c (revision 17943) @@ -194,12 +194,11 @@ iseq->coverage = Qfalse; if (!GET_THREAD()->parse_in_eval) { - if (rb_const_defined_at(rb_cObject, rb_intern("COVERAGE__"))) { - VALUE hash = rb_const_get_at(rb_cObject, rb_intern("COVERAGE__")); - if (TYPE(hash) == T_HASH) { - iseq->coverage = rb_hash_aref(hash, filename); - if (NIL_P(iseq->coverage)) iseq->coverage = Qfalse; - } + extern VALUE rb_vm_get_coverages(void); + VALUE coverages = rb_vm_get_coverages(); + if (RTEST(coverages)) { + iseq->coverage = rb_hash_aref(coverages, filename); + if (NIL_P(iseq->coverage)) iseq->coverage = Qfalse; } } Index: win32-unicode-test/io.c =================================================================== --- win32-unicode-test/io.c (revision 17942) +++ win32-unicode-test/io.c (revision 17943) @@ -148,13 +148,7 @@ do { \ if (max_file_descriptor < (fd)) max_file_descriptor = (fd); \ } while (0) -#define UPDATE_MAXFD_PIPE(filedes) \ - do { \ - UPDATE_MAXFD((filedes)[0]); \ - UPDATE_MAXFD((filedes)[1]); \ - } while (0) - #define argf_of(obj) (*(struct argf *)DATA_PTR(obj)) #define ARGF argf_of(argf) @@ -3650,6 +3644,24 @@ rb_io_synchronized(fptr); } +int +rb_pipe(int *pipes) +{ + int ret; + ret = pipe(pipes); + if (ret == -1) { + if (errno == EMFILE || errno == ENFILE) { + rb_gc(); + ret = pipe(pipes); + } + } + if (ret == 0) { + UPDATE_MAXFD(pipes[0]); + UPDATE_MAXFD(pipes[1]); + } + return ret; +} + #ifdef HAVE_FORK struct popen_arg { struct rb_exec_arg *execp; @@ -3772,33 +3784,29 @@ arg.write_pair[0] = arg.write_pair[1] = -1; switch (modef & (FMODE_READABLE|FMODE_WRITABLE)) { case FMODE_READABLE|FMODE_WRITABLE: - if (pipe(arg.write_pair) < 0) + if (rb_pipe(arg.write_pair) < 0) rb_sys_fail(cmd); - UPDATE_MAXFD_PIPE(arg.write_pair); - if (pipe(arg.pair) < 0) { + if (rb_pipe(arg.pair) < 0) { int e = errno; close(arg.write_pair[0]); close(arg.write_pair[1]); errno = e; rb_sys_fail(cmd); } - UPDATE_MAXFD_PIPE(arg.pair); if (eargp) { rb_exec_arg_addopt(eargp, INT2FIX(0), INT2FIX(arg.write_pair[0])); rb_exec_arg_addopt(eargp, INT2FIX(1), INT2FIX(arg.pair[1])); } break; case FMODE_READABLE: - if (pipe(arg.pair) < 0) + if (rb_pipe(arg.pair) < 0) rb_sys_fail(cmd); - UPDATE_MAXFD_PIPE(arg.pair); if (eargp) rb_exec_arg_addopt(eargp, INT2FIX(1), INT2FIX(arg.pair[1])); break; case FMODE_WRITABLE: - if (pipe(arg.pair) < 0) + if (rb_pipe(arg.pair) < 0) rb_sys_fail(cmd); - UPDATE_MAXFD_PIPE(arg.pair); if (eargp) rb_exec_arg_addopt(eargp, INT2FIX(0), INT2FIX(arg.pair[0])); break; @@ -6225,9 +6233,8 @@ rb_io_t *fptr; rb_scan_args(argc, argv, "02", &v1, &v2); - if (pipe(pipes) == -1) - rb_sys_fail(0); - UPDATE_MAXFD_PIPE(pipes); + if (rb_pipe(pipes) == -1) + rb_sys_fail(0); args[0] = klass; args[1] = INT2NUM(pipes[0]); Index: win32-unicode-test/lib/coverage.rb =================================================================== --- win32-unicode-test/lib/coverage.rb (revision 17942) +++ win32-unicode-test/lib/coverage.rb (revision 17943) @@ -1,4 +1,5 @@ -COVERAGE__ ||= {} +require "coverage.so" + ext = ENV["COVERUBY_EXT"] || ".cov" accum = ENV["COVERUBY_ACCUM"] accum = !accum || accum == "" || !(%w(f n 0).include?(accum[0])) @@ -6,7 +7,7 @@ at_exit do Dir.chdir(pwd) do - COVERAGE__.each do |sfile, covs| + Coverage.result.each do |sfile, covs| cfile = sfile + ext writable = proc do |f| Index: win32-unicode-test/lib/ipaddr.rb =================================================================== --- win32-unicode-test/lib/ipaddr.rb (revision 17942) +++ win32-unicode-test/lib/ipaddr.rb (revision 17943) @@ -483,7 +483,7 @@ if prefixlen mask!(prefixlen) else - @mask_addr = (family == Socket::AF_INET) ? IN4MASK : IN6MASK + @mask_addr = (@family == Socket::AF_INET) ? IN4MASK : IN6MASK end end Index: win32-unicode-test/lib/test/unit/autorunner.rb =================================================================== --- win32-unicode-test/lib/test/unit/autorunner.rb (revision 17942) +++ win32-unicode-test/lib/test/unit/autorunner.rb (revision 17943) @@ -14,10 +14,7 @@ def self.standalone? return false unless("-e" == $0) - ObjectSpace.each_object(Class) do |klass| - return false if(klass < TestCase) - end - true + TestCase::DECENDANT_CLASSES.empty? end RUNNERS = { Index: win32-unicode-test/lib/test/unit/collector/dir.rb =================================================================== --- win32-unicode-test/lib/test/unit/collector/dir.rb (revision 17942) +++ win32-unicode-test/lib/test/unit/collector/dir.rb (revision 17943) @@ -10,7 +10,7 @@ attr_reader :pattern, :exclude attr_accessor :base - def initialize(dir=::Dir, file=::File, object_space=::ObjectSpace, req=nil) + def initialize(dir=::Dir, file=::File, object_space=nil, req=nil) super() @dir = dir @file = file @@ -43,8 +43,14 @@ def find_test_cases(ignore=[]) cases = [] - @object_space.each_object(Class) do |c| - cases << c if(c < TestCase && !ignore.include?(c)) + if @object_space + @object_space.each_object(Class) do |c| + cases << c if(c < TestCase && !ignore.include?(c)) + end + else + TestCase::DECENDANT_CLASSES.each do |c| + cases << c if !ignore.include?(c) + end end ignore.concat(cases) cases Index: win32-unicode-test/lib/test/unit/collector/objectspace.rb =================================================================== --- win32-unicode-test/lib/test/unit/collector/objectspace.rb (revision 17942) +++ win32-unicode-test/lib/test/unit/collector/objectspace.rb (revision 17943) @@ -10,9 +10,9 @@ class ObjectSpace include Test::Unit::Collector - NAME = 'collected from the ObjectSpace' + NAME = 'collected from the subclasses of TestCase' - def initialize(source=::ObjectSpace) + def initialize(source=nil) super() @source = source end @@ -20,8 +20,14 @@ def collect(name=NAME) suite = TestSuite.new(name) sub_suites = [] - @source.each_object(Class) do |klass| - if(Test::Unit::TestCase > klass) + if @source + @source.each_object(Class) do |klass| + if(Test::Unit::TestCase > klass) + add_suite(sub_suites, klass.suite) + end + end + else + TestCase::DECENDANT_CLASSES.each do |klass| add_suite(sub_suites, klass.suite) end end Index: win32-unicode-test/lib/test/unit/testcase.rb =================================================================== --- win32-unicode-test/lib/test/unit/testcase.rb (revision 17942) +++ win32-unicode-test/lib/test/unit/testcase.rb (revision 17943) @@ -34,6 +34,11 @@ PASSTHROUGH_EXCEPTIONS = [NoMemoryError, SignalException, Interrupt, SystemExit] + DECENDANT_CLASSES = [] + def self.inherited(decendant) + DECENDANT_CLASSES << decendant + end + # Creates a new instance of the fixture for running the # test represented by test_method_name. def initialize(test_method_name) Index: win32-unicode-test/lib/net/smtp.rb =================================================================== --- win32-unicode-test/lib/net/smtp.rb (revision 17942) +++ win32-unicode-test/lib/net/smtp.rb (revision 17943) @@ -437,7 +437,7 @@ # +port+ is the port to connect to; it defaults to port 25. # # +helo+ is the _HELO_ _domain_ provided by the client to the - # server (see overview comments); it defaults to 'localhost.localdomain'. + # server (see overview comments); it defaults to 'localhost'. # # The remaining arguments are used for SMTP authentication, if required # or desired. +user+ is the account name; +secret+ is your password @@ -457,7 +457,7 @@ # * IOError # * TimeoutError # - def SMTP.start(address, port = nil, helo = 'localhost.localdomain', + def SMTP.start(address, port = nil, helo = 'localhost', user = nil, secret = nil, authtype = nil, &block) # :yield: smtp new(address, port).start(helo, user, secret, authtype, &block) @@ -518,7 +518,7 @@ # * IOError # * TimeoutError # - def start(helo = 'localhost.localdomain', + def start(helo = 'localhost', user = nil, secret = nil, authtype = nil) # :yield: smtp if block_given? begin Index: win32-unicode-test/lib/net/ftp.rb =================================================================== --- win32-unicode-test/lib/net/ftp.rb (revision 17942) +++ win32-unicode-test/lib/net/ftp.rb (revision 17943) @@ -296,12 +296,9 @@ def sendport(host, port) af = (@sock.peeraddr)[0] if af == "AF_INET" - hbytes = host.split(".") - pbytes = [port / 256, port % 256] - bytes = hbytes + pbytes - cmd = "PORT " + bytes.join(",") + cmd = "PORT " + (host.split(".") + port.divmod(256)).join(",") elsif af == "AF_INET6" - cmd = "EPRT |2|" + host + "|" + sprintf("%d", port) + "|" + cmd = sprintf("EPRT |2|%s|%d|", host, port) else raise FTPProtoError, host end Index: win32-unicode-test/proc.c =================================================================== --- win32-unicode-test/proc.c (revision 17942) +++ win32-unicode-test/proc.c (revision 17943) @@ -1760,7 +1760,8 @@ rb_define_method(rb_eLocalJumpError, "reason", localjump_reason, 0); rb_eSysStackError = rb_define_class("SystemStackError", rb_eException); - sysstack_error = rb_exc_new2(rb_eSysStackError, "stack level too deep"); + sysstack_error = rb_exc_new3(rb_eSysStackError, + rb_obj_freeze(rb_str_new2("stack level too deep"))); OBJ_TAINT(sysstack_error); OBJ_FREEZE(sysstack_error); Index: win32-unicode-test/thread.c =================================================================== --- win32-unicode-test/thread.c (revision 17942) +++ win32-unicode-test/thread.c (revision 17943) @@ -151,6 +151,7 @@ #endif NOINLINE(static int thread_start_func_2(rb_thread_t *th, VALUE *stack_start, VALUE *register_stack_start)); +static void timer_thread_function(void *); #if defined(_WIN32) #include "thread_win32.c" @@ -2050,9 +2051,9 @@ int rb_get_next_signal(rb_vm_t *vm); static void -timer_thread_function(void) +timer_thread_function(void *arg) { - rb_vm_t *vm = GET_VM(); /* TODO: fix me for Multi-VM */ + rb_vm_t *vm = arg; /* TODO: fix me for Multi-VM */ /* for time slice */ RUBY_VM_SET_TIMER_INTERRUPT(vm->running_thread); @@ -2116,11 +2117,10 @@ static void clear_coverage(void) { - if (rb_const_defined_at(rb_cObject, rb_intern("COVERAGE__"))) { - VALUE hash = rb_const_get_at(rb_cObject, rb_intern("COVERAGE__")); - if (TYPE(hash) == T_HASH) { - st_foreach(RHASH_TBL(hash), clear_coverage_i, 0); - } + extern VALUE rb_vm_get_coverages(void); + VALUE coverages = rb_vm_get_coverages(); + if (RTEST(coverages)) { + st_foreach(RHASH_TBL(coverages), clear_coverage_i, 0); } } @@ -3530,3 +3530,34 @@ rb_thread_raise(2, argv, vm->main_thread); } } + +static void +update_coverage(rb_event_flag_t event, VALUE proc, VALUE self, ID id, VALUE klass) +{ + VALUE coverage = GET_THREAD()->cfp->iseq->coverage; + if (coverage) { + long line = rb_sourceline() - 1; + long count; + if (RARRAY_PTR(coverage)[line] == Qnil) { + rb_bug("bug"); + } + count = FIX2LONG(RARRAY_PTR(coverage)[line]) + 1; + if (POSFIXABLE(count)) { + RARRAY_PTR(coverage)[line] = LONG2FIX(count); + } + } +} + +void +rb_enable_coverages(void) +{ + VALUE rb_mCoverage; + + if (!RTEST(GET_VM()->coverages)) { + extern VALUE rb_vm_get_coverages(void); + GET_VM()->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); + } +} Index: win32-unicode-test/win32/win32.c =================================================================== --- win32-unicode-test/win32/win32.c (revision 17942) +++ win32-unicode-test/win32/win32.c (revision 17943) @@ -12,7 +12,6 @@ #include "ruby/ruby.h" #include "ruby/signal.h" -#include "ruby/encoding.h" #include "dln.h" #include <fcntl.h> #include <process.h> @@ -3934,28 +3933,6 @@ return rb_w32_send(fd, buf, size, 0); } -long -rb_w32_write_console(VALUE str, int fd) -{ - static int disable; - HANDLE handle; - DWORD dwMode, reslen; - - if (disable) return -1L; - handle = (HANDLE)_osfhnd(fd); - if (!GetConsoleMode(handle, &dwMode) || - !rb_transcode_convertible(rb_enc_name(rb_enc_get(str)), "UTF-16LE")) - return -1L; - - str = rb_str_transcode(str, rb_str_new2("UTF-16LE")); - if (!WriteConsoleW(handle, (LPWSTR)RSTRING_PTR(str), RSTRING_LEN(str)/2, &reslen, NULL)) { - if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) - disable = TRUE; - return -1L; - } - return (long)reslen; -} - static int unixtime_to_filetime(time_t time, FILETIME *ft) { Index: win32-unicode-test/sprintf.c =================================================================== --- win32-unicode-test/sprintf.c (revision 17942) +++ win32-unicode-test/sprintf.c (revision 17943) @@ -17,6 +17,10 @@ #include <math.h> #include <stdarg.h> +#ifdef HAVE_IEEEFP_H +#include <ieeefp.h> +#endif + #define BIT_DIGITS(N) (((N)*146)/485 + 1) /* log2(10) =~ 146/485 */ #define BITSPERDIG (SIZEOF_BDIGITS*CHAR_BIT) #define EXTENDSIGN(n, l) (((~0 << (n)) >> (((n)*(l)) % BITSPERDIG)) & ~(~0 << (n))) Index: win32-unicode-test/eval.c =================================================================== --- win32-unicode-test/eval.c (revision 17942) +++ win32-unicode-test/eval.c (revision 17943) @@ -1201,7 +1201,8 @@ rb_define_virtual_variable("$SAFE", safe_getter, safe_setter); - exception_error = rb_exc_new2(rb_eFatal, "exception reentered"); + exception_error = rb_exc_new3(rb_eFatal, + rb_obj_freeze(rb_str_new2("exception reentered"))); rb_ivar_set(exception_error, idThrowState, INT2FIX(TAG_FATAL)); OBJ_TAINT(exception_error); OBJ_FREEZE(exception_error); Index: win32-unicode-test/gc.c =================================================================== --- win32-unicode-test/gc.c (revision 17942) +++ win32-unicode-test/gc.c (revision 17943) @@ -129,17 +129,10 @@ #pragma pack(pop) #endif -enum slot_color { - WHITE = 0x00, /* garbage */ - BLACK = 0x01, /* used */ - GRAY = 0x02, /* not sweep */ -}; - struct heaps_slot { void *membase; RVALUE *slot; int limit; - enum slot_color color; }; #define HEAP_MIN_SLOTS 10000 @@ -169,11 +162,6 @@ RVALUE *freelist; RVALUE *range[2]; RVALUE *freed; - size_t live; - size_t dead; - size_t do_heap_free; - size_t sweep_index; - size_t sweep_increment; } heap; struct { int dont_gc; @@ -212,11 +200,6 @@ #define himem objspace->heap.range[1] #define heaps_inc objspace->heap.increment #define heaps_freed objspace->heap.freed -#define live objspace->heap.live -#define dead objspace->heap.dead -#define do_heap_free objspace->heap.do_heap_free -#define heaps_sweep_index objspace->heap.sweep_index -#define heaps_sweep_inc objspace->heap.sweep_increment #define dont_gc objspace->flags.dont_gc #define during_gc objspace->flags.during_gc #define finalizer_table objspace->final.table @@ -266,7 +249,6 @@ static void run_final(rb_objspace_t *objspace, VALUE obj); static int garbage_collect(rb_objspace_t *objspace); -static int garbage_collect_force(rb_objspace_t *objspace); void rb_global_variable(VALUE *var) @@ -343,11 +325,11 @@ if ((ruby_gc_stress && !ruby_disable_gc_stress) || (malloc_increase+size) > malloc_limit) { - garbage_collect_force(objspace); + garbage_collect(objspace); } RUBY_CRITICAL(mem = malloc(size)); if (!mem) { - if (garbage_collect_force(objspace)) { + if (garbage_collect(objspace)) { RUBY_CRITICAL(mem = malloc(size)); } if (!mem) { @@ -383,9 +365,10 @@ objspace->malloc_params.allocated_size -= size; ptr = (size_t *)ptr - 1; #endif + RUBY_CRITICAL(mem = realloc(ptr, size)); if (!mem) { - if (garbage_collect_force(objspace)) { + if (garbage_collect(objspace)) { RUBY_CRITICAL(mem = realloc(ptr, size)); } if (!mem) { @@ -576,8 +559,6 @@ heaps_length = next_heaps_length; } -#define RANY(o) ((RVALUE*)(o)) - static void assign_heap_slot(rb_objspace_t *objspace) { @@ -621,7 +602,6 @@ heaps[hi].membase = membase; heaps[hi].slot = p; heaps[hi].limit = objs; - heaps[hi].color = BLACK; pend = p + objs; if (lomem == 0 || lomem > p) lomem = p; if (himem < pend) himem = pend; @@ -633,9 +613,6 @@ freelist = p; p++; } - if (hi < heaps_sweep_index) { - heaps_sweep_index++; - } } static void @@ -678,13 +655,15 @@ return Qfalse; } +#define RANY(o) ((RVALUE*)(o)) + static VALUE rb_newobj_from_heap(rb_objspace_t *objspace) { VALUE obj; if ((ruby_gc_stress && !ruby_disable_gc_stress) || !freelist) { - if (!garbage_collect(objspace)) { + if (!heaps_increment(objspace) && !garbage_collect(objspace)) { rb_memerror(); } } @@ -726,17 +705,7 @@ int rb_during_gc(void) { -#if USE_VALUE_CACHE - rb_thread_t *th = GET_THREAD(); - VALUE v = *th->value_cache_ptr; -#if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE - rb_objspace_t *objspace = th->vm->objspace; -#else rb_objspace_t *objspace = &rb_objspace; -#endif -#else - rb_objspace_t *objspace = &rb_objspace; -#endif return during_gc; } @@ -1071,7 +1040,6 @@ if (obj->as.basic.flags == 0) return; /* free cell */ if (obj->as.basic.flags & FL_MARK) return; /* already marked */ obj->as.basic.flags |= FL_MARK; - live++; if (lev > GC_LEVEL_MAX || (lev == 0 && ruby_stack_check())) { if (!mark_stack_overflow) { @@ -1107,7 +1075,6 @@ if (obj->as.basic.flags == 0) return; /* free cell */ if (obj->as.basic.flags & FL_MARK) return; /* already marked */ obj->as.basic.flags |= FL_MARK; - live++; marking: if (FL_TEST(obj, FL_EXIVAR)) { @@ -1367,133 +1334,139 @@ if (!FL_TEST(p, FL_SINGLETON)) { /* not freeing page */ VALGRIND_MAKE_MEM_UNDEFINED((void*)p, sizeof(RVALUE)); p->as.free.flags = 0; + p->as.free.next = freelist; + freelist = p; } p = tmp; } } -void rb_gc_abort_threads(void); - -static int -slot_sweep(rb_objspace_t *objspace, struct heaps_slot *target) +static void +free_unused_heaps(rb_objspace_t *objspace) { - RVALUE *p, *pend, *free; - RVALUE *final; - int freed = 0; + size_t i, j; + RVALUE *last = 0; - if (target->color == BLACK || target->color == WHITE) { - return Qfalse; - } - - final = deferred_final_list; - free = freelist; - p = target->slot; pend = p + target->limit; - while (p < pend) { - if (!(p->as.basic.flags & FL_MARK)) { - if (p->as.basic.flags) { - obj_free(objspace, (VALUE)p); + for (i = j = 1; j < heaps_used; i++) { + if (heaps[i].limit == 0) { + if (!last) { + last = heaps[i].membase; } - if (need_call_final && FL_TEST(p, FL_FINALIZE)) { - p->as.free.flags = FL_MARK; /* remain marked */ - p->as.free.next = deferred_final_list; - deferred_final_list = p; - } else { - VALGRIND_MAKE_MEM_UNDEFINED((void*)p, sizeof(RVALUE)); - p->as.free.flags = 0; - p->as.free.next = freelist; - freelist = p; + free(heaps[i].membase); } - freed++; + heaps_used--; } - else if (RBASIC(p)->flags == FL_MARK) { - /* objects to be finalized */ - /* do nothing remain marked */ - } else { - p->as.basic.flags &= ~FL_MARK; + if (i != j) { + heaps[j] = heaps[i]; + } + j++; } - p++; } - dead += freed; - if (freed == target->limit && dead > do_heap_free) { - RVALUE *pp; - - target->limit = 0; - target->color = WHITE; - for (pp = deferred_final_list; pp != final; pp = pp->as.free.next) { - pp->as.free.flags |= FL_SINGLETON; /* freeing page mark */ + if (last) { + if (last < heaps_freed) { + free(heaps_freed); + heaps_freed = last; } - freelist = free; /* cancel this page from freelist */ + else { + free(last); + } } - else { - target->color = BLACK; - } - return Qtrue; } static void -heap_sweep_increment(rb_objspace_t *objspace) +gc_sweep(rb_objspace_t *objspace) { - int i = 0; + RVALUE *p, *pend, *final_list; + size_t freed = 0; + size_t i; + size_t live = 0, free_min = 0, do_heap_free = 0; - while (i < heaps_sweep_inc && heaps_sweep_index < heaps_used) { - if (slot_sweep(objspace, &heaps[heaps_sweep_index])) { - i++; - } - heaps_sweep_index++; + do_heap_free = (heaps_used * HEAP_OBJ_LIMIT) * 0.65; + free_min = (heaps_used * HEAP_OBJ_LIMIT) * 0.2; + if (free_min < FREE_MIN) { + do_heap_free = heaps_used * HEAP_OBJ_LIMIT; + free_min = FREE_MIN; } -} -static void -heap_sweep(rb_objspace_t *objspace) -{ - while (!freelist && heaps_sweep_index < heaps_used) { - slot_sweep(objspace, &heaps[heaps_sweep_index]); - heaps_sweep_index++; - } -} + freelist = 0; + final_list = deferred_final_list; + deferred_final_list = 0; + for (i = 0; i < heaps_used; i++) { + int n = 0; + RVALUE *free = freelist; + RVALUE *final = final_list; -#define GC_NOT_LAZY_SWEEP 0 + p = heaps[i].slot; pend = p + heaps[i].limit; + while (p < pend) { + if (!(p->as.basic.flags & FL_MARK)) { + if (p->as.basic.flags) { + obj_free(objspace, (VALUE)p); + } + if (need_call_final && FL_TEST(p, FL_FINALIZE)) { + p->as.free.flags = FL_MARK; /* remain marked */ + p->as.free.next = final_list; + final_list = p; + } + else { + VALGRIND_MAKE_MEM_UNDEFINED((void*)p, sizeof(RVALUE)); + p->as.free.flags = 0; + p->as.free.next = freelist; + freelist = p; + } + n++; + } + else if (RBASIC(p)->flags == FL_MARK) { + /* objects to be finalized */ + /* do nothing remain marked */ + } + else { + RBASIC(p)->flags &= ~FL_MARK; + live++; + } + p++; + } + if (n == heaps[i].limit && freed > do_heap_free) { + RVALUE *pp; -#ifdef GC_NOT_LAZY_SWEEP -static void -heap_all_sweep(rb_objspace_t *objspace) -{ - while (heaps_sweep_index < heaps_used) { - slot_sweep(objspace, &heaps[heaps_sweep_index]); - heaps_sweep_index++; + heaps[i].limit = 0; + for (pp = final_list; pp != final; pp = pp->as.free.next) { + p->as.free.flags |= FL_SINGLETON; /* freeing page mark */ + } + freelist = free; /* cancel this page from freelist */ + } + else { + freed += n; + } } -} -#endif - -static int -gc_lazy_sweep(rb_objspace_t *objspace, rb_thread_t *th) -{ - - if (heaps_increment(objspace)) { - heap_sweep_increment(objspace); + if (malloc_increase > malloc_limit) { + malloc_limit += (malloc_increase - malloc_limit) * (double)live / (live + freed); + if (malloc_limit < GC_MALLOC_LIMIT) malloc_limit = GC_MALLOC_LIMIT; } - else { - heap_sweep(objspace); + malloc_increase = 0; + if (freed < free_min) { + set_heaps_increment(objspace); + heaps_increment(objspace); } + during_gc = 0; -#ifdef GC_NOT_LAZY_SWEEP - if (GC_NOT_LAZY_SWEEP) heap_all_sweep(objspace); -#endif - - if (!freelist) { - return Qfalse; + /* clear finalization list */ + if (final_list) { + deferred_final_list = final_list; + return; } - - return Qtrue; + free_unused_heaps(objspace); } void rb_gc_force_recycle(VALUE p) { + rb_objspace_t *objspace = &rb_objspace; VALGRIND_MAKE_MEM_UNDEFINED((void*)p, sizeof(RVALUE)); RANY(p)->as.free.flags = 0; + RANY(p)->as.free.next = freelist; + freelist = RANY(p); } static void @@ -1694,87 +1667,30 @@ void rb_gc_mark_encodings(void); -static void -gc_mark_all_clear(rb_objspace_t *objspace) +static int +garbage_collect(rb_objspace_t *objspace) { - RVALUE *last = 0; - size_t i, j; - - for (i = j = 0; j < heaps_used; i++) { - if (heaps[i].color == WHITE && !deferred_final_list) { - if (!last) { - last = heaps[i].membase; - } - else { - free(heaps[i].membase); - } - heaps_used--; - } - else { - if (heaps[i].color == GRAY) { - RVALUE *p, *pend; - p = heaps[i].slot; pend = p + heaps[i].limit; - while (p < pend) { - if (!(RBASIC(p)->flags & FL_MARK)) { - if (p->as.basic.flags && !FL_TEST(p, FL_FINALIZE)) { - obj_free(objspace, (VALUE)p); - VALGRIND_MAKE_MEM_UNDEFINED((void*)p, sizeof(RVALUE)); - p->as.free.flags = 0; - } - } - else if (RBASIC(p)->flags != FL_MARK) { - p->as.basic.flags &= ~FL_MARK; - } - p++; - } - } - else { - heaps[i].color = GRAY; - } - if (i != j) { - heaps[j] = heaps[i]; - } - j++; - } - } - if (last) { - if (last < heaps_freed) { - free(heaps_freed); - heaps_freed = last; - } - else { - free(last); - } - } -} + struct gc_list *list; + rb_thread_t *th = GET_THREAD(); -static void -set_lazy_sweep_params(rb_objspace_t *objspace) -{ - size_t free_min = 0; + if (GC_NOTIFY) printf("start garbage_collect()\n"); - dead = 0; - heaps_sweep_index = 0; - heaps_sweep_inc = (heaps_used / 10) + 1; - do_heap_free = (heaps_used * HEAP_OBJ_LIMIT) * 0.65; - free_min = (heaps_used * HEAP_OBJ_LIMIT) * 0.2; - if (free_min < FREE_MIN) free_min = FREE_MIN; - if (free_min > (heaps_used * HEAP_OBJ_LIMIT - live)) { - set_heaps_increment(objspace); - heaps_sweep_inc = (heaps_used + heaps_sweep_inc) / heaps_sweep_inc + 1; + if (!heaps) { + return Qfalse; } -} -static void -gc_marks(rb_objspace_t *objspace, rb_thread_t *th) -{ - struct gc_list *list; + if (dont_gc || during_gc) { + if (!freelist) { + if (!heaps_increment(objspace)) { + set_heaps_increment(objspace); + heaps_increment(objspace); + } + } + return Qtrue; + } + during_gc++; + objspace->count++; - live = 0; - freelist = 0; - - gc_mark_all_clear(objspace); - SET_STACK_END; init_mark_stack(objspace); @@ -1791,7 +1707,6 @@ rb_gc_mark_symbols(); rb_gc_mark_encodings(); - /* mark protected global variables */ for (list = global_List; list; list = list->next) { rb_gc_mark_maybe(*list->varptr); @@ -1817,51 +1732,9 @@ } } - set_lazy_sweep_params(objspace); -} + gc_sweep(objspace); -static int -garbage_collect_force(rb_objspace_t *objspace) -{ - if (malloc_increase > malloc_limit) { - malloc_limit += (malloc_increase - malloc_limit) * (double)live / (heaps_used * HEAP_OBJ_LIMIT); - if (malloc_limit < GC_MALLOC_LIMIT) malloc_limit = GC_MALLOC_LIMIT; - } - malloc_increase = 0; - gc_marks(objspace, GET_THREAD()); - return garbage_collect(objspace); -} - -static int -garbage_collect(rb_objspace_t *objspace) -{ - rb_thread_t *th = GET_THREAD(); - - if (GC_NOTIFY) printf("start garbage_collect()\n"); - - if (!heaps) { - return Qfalse; - } - - if (dont_gc || during_gc) { - if (!freelist) { - if (!heaps_increment(objspace)) { - set_heaps_increment(objspace); - heaps_increment(objspace); - } - } - return Qtrue; - } - during_gc++; - objspace->count++; - - while (!gc_lazy_sweep(objspace, th)) { - gc_marks(objspace, th); - } - if (GC_NOTIFY) printf("end garbage_collect()\n"); - during_gc = 0; - return Qtrue; } @@ -2161,6 +2034,7 @@ if (p) { finalize_list(objspace, p); } + free_unused_heaps(objspace); } void @@ -2232,8 +2106,8 @@ rb_gc(void) { rb_objspace_t *objspace = &rb_objspace; - gc_finalize_deferred(objspace); garbage_collect(objspace); + gc_finalize_deferred(objspace); } /* @@ -2541,7 +2415,8 @@ rb_define_module_function(rb_mObSpace, "_id2ref", id2ref, 1); - nomem_error = rb_exc_new2(rb_eNoMemError, "failed to allocate memory"); + nomem_error = rb_exc_new3(rb_eNoMemError, + rb_obj_freeze(rb_str_new2("failed to allocate memory"))); OBJ_TAINT(nomem_error); OBJ_FREEZE(nomem_error); Index: win32-unicode-test/regint.h =================================================================== --- win32-unicode-test/regint.h (revision 17942) +++ win32-unicode-test/regint.h (revision 17943) @@ -262,13 +262,13 @@ #define GET_ALIGNMENT_PAD_SIZE(addr,pad_size) do {\ (pad_size) = WORD_ALIGNMENT_SIZE \ - - ((unsigned int )(addr) % WORD_ALIGNMENT_SIZE);\ + - ((uintptr_t )(addr) % WORD_ALIGNMENT_SIZE);\ if ((pad_size) == WORD_ALIGNMENT_SIZE) (pad_size) = 0;\ } while (0) #define ALIGNMENT_RIGHT(addr) do {\ (addr) += (WORD_ALIGNMENT_SIZE - 1);\ - (addr) -= ((unsigned int )(addr) % WORD_ALIGNMENT_SIZE);\ + (addr) -= ((uintptr_t )(addr) % WORD_ALIGNMENT_SIZE);\ } while (0) #endif /* PLATFORM_UNALIGNED_WORD_ACCESS */ Index: win32-unicode-test/parse.y =================================================================== --- win32-unicode-test/parse.y (revision 17942) +++ win32-unicode-test/parse.y (revision 17943) @@ -4672,17 +4672,16 @@ static VALUE coverage(const char *f, int n) { - if (rb_const_defined_at(rb_cObject, rb_intern("COVERAGE__"))) { - VALUE hash = rb_const_get_at(rb_cObject, rb_intern("COVERAGE__")); - if (TYPE(hash) == T_HASH) { - VALUE fname = rb_str_new2(f); - VALUE lines = rb_ary_new2(n); - int i; - for (i = 0; i < n; i++) RARRAY_PTR(lines)[i] = Qnil; - RARRAY(lines)->len = n; - rb_hash_aset(hash, fname, lines); - return lines; - } + extern VALUE rb_vm_get_coverages(void); + VALUE coverages = rb_vm_get_coverages(); + if (RTEST(coverages)) { + VALUE fname = rb_str_new2(f); + VALUE lines = rb_ary_new2(n); + int i; + for (i = 0; i < n; i++) RARRAY_PTR(lines)[i] = Qnil; + RARRAY(lines)->len = n; + rb_hash_aset(coverages, fname, lines); + return lines; } return 0; } Index: win32-unicode-test/Makefile.in =================================================================== --- win32-unicode-test/Makefile.in (revision 17942) +++ win32-unicode-test/Makefile.in (revision 17943) @@ -86,6 +86,7 @@ ARCHFILE = @ARCHFILE@ SETUP = EXTSTATIC = @EXTSTATIC@ +SET_LC_MESSAGES = env LC_MESSAGES=C CP = cp MV = mv Index: win32-unicode-test/process.c =================================================================== --- win32-unicode-test/process.c (revision 17942) +++ win32-unicode-test/process.c (revision 17943) @@ -2255,7 +2255,7 @@ pipe_nocrash(int filedes[2], VALUE fds) { int ret; - ret = pipe(filedes); + ret = rb_pipe(filedes); if (ret == -1) return -1; if (RTEST(fds)) { @@ -2778,7 +2778,11 @@ * * If a hash is given as +env+, the environment is * updated by +env+ before <code>exec(2)</code> in the child process. + * If a pair in +env+ has nil as the value, the variable is deleted. * + * # set FOO as BAR and unset BAZ. + * pid = spawn({"FOO"=>"BAR", "BAZ"=>nil}, command) + * * If a hash is given as +options+, * it specifies * process group, Index: win32-unicode-test/ext/bigdecimal/bigdecimal.c =================================================================== --- win32-unicode-test/ext/bigdecimal/bigdecimal.c (revision 17942) +++ win32-unicode-test/ext/bigdecimal/bigdecimal.c (revision 17943) @@ -22,6 +22,10 @@ #include <float.h> #include <math.h> #include "math.h" + +#ifdef HAVE_IEEEFP_H +#include <ieeefp.h> +#endif /* #define ENABLE_NUMERIC_STRING */ Index: win32-unicode-test/ext/coverage/extconf.rb =================================================================== --- win32-unicode-test/ext/coverage/extconf.rb (revision 0) +++ win32-unicode-test/ext/coverage/extconf.rb (revision 17943) @@ -0,0 +1,2 @@ +require 'mkmf' +create_makefile('coverage') Property changes on: win32-unicode-test/ext/coverage/extconf.rb ___________________________________________________________________ Name: svn:eol-style + LF Index: win32-unicode-test/ext/coverage/coverage.c =================================================================== --- win32-unicode-test/ext/coverage/coverage.c (revision 0) +++ win32-unicode-test/ext/coverage/coverage.c (revision 17943) @@ -0,0 +1,47 @@ +/************************************************ + + coverage.c - + + $Author: $ + + Copyright (c) 2008 Yusuke Endoh + +************************************************/ + +#include "ruby.h" + +extern void rb_enable_coverages(void); + +/* Coverage provides coverage measurement feature for Ruby. + * + * = 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 + * coverage array as value. + * + * = Example + * + * [foo.rb] + * s = 0 + * 10.times do |x| + * s += x + * end + * + * if s == 45 + * p :ok + * else + * p :ng + * end + * [EOF] + * + * require "coverage.so" + * require "foo.rb" + * p COVERAGE__ #=> {"foo.rb"=>[1, 1, 10, nil, nil, 1, 1, nil, 0, nil]} + */ +void +Init_coverage(void) +{ + rb_enable_coverages(); +} Property changes on: win32-unicode-test/ext/coverage/coverage.c ___________________________________________________________________ Name: svn:eol-style + LF Property changes on: win32-unicode-test/ext/coverage ___________________________________________________________________ Name: svn:ignore + extconf.h Makefile Index: win32-unicode-test/ext/win32ole/win32ole.c =================================================================== --- win32-unicode-test/ext/win32ole/win32ole.c (revision 17942) +++ win32-unicode-test/ext/win32ole/win32ole.c (revision 17943) @@ -24,6 +24,7 @@ #include <olectl.h> #include <ole2.h> #include <stdlib.h> +#include <math.h> #ifdef HAVE_STDARG_PROTOTYPES #include <stdarg.h> #define va_init_list(a,b) va_start(a,b) @@ -117,7 +118,7 @@ #define WC2VSTR(x) ole_wc2vstr((x), TRUE) -#define WIN32OLE_VERSION "1.1.8" +#define WIN32OLE_VERSION "1.2.1" typedef HRESULT (STDAPICALLTYPE FNCOCREATEINSTANCEEX) (REFCLSID, IUnknown*, DWORD, COSERVERINFO*, DWORD, MULTI_QI*); @@ -367,6 +368,7 @@ static VALUE ole_typelib_from_itypeinfo(ITypeInfo *pTypeInfo); static VALUE fole_typelib(VALUE self); static VALUE fole_query_interface(VALUE self, VALUE str_iid); +static VALUE fole_respond_to(VALUE self, VALUE method); static HRESULT ole_docinfo_from_type(ITypeInfo *pTypeInfo, BSTR *name, BSTR *helpstr, DWORD *helpcontext, BSTR *helpfile); static VALUE ole_usertype2val(ITypeInfo *pTypeInfo, TYPEDESC *pTypeDesc, VALUE typedetails); static VALUE ole_ptrtype2val(ITypeInfo *pTypeInfo, TYPEDESC *pTypeDesc, VALUE typedetails); @@ -422,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); @@ -763,7 +768,7 @@ double d_hh, d_mm, d_ss; int i_hh, i_mm, i_ss; - double d = v * 86400.0; + double d = fabs(v * 86400.0); d_hh = d / 3600.0; i_hh = (int)d_hh; @@ -4373,6 +4378,32 @@ return create_win32ole_object(cWIN32OLE, pDispatch, 0, 0); } +/* + * call-seq: + * WIN32OLE#ole_respond_to?(method) -> true or false + * + * Returns true when OLE object has OLE method, otherwise returns false. + * + * ie = WIN32OLE.new('InternetExplorer.Application') + * ie.ole_respond_to?("gohome") => true + */ +static VALUE +fole_respond_to(VALUE self, VALUE method) +{ + struct oledata *pole; + BSTR wcmdname; + DISPID DispID; + HRESULT hr; + rb_secure(4); + Check_SafeStr(method); + OLEData_Get_Struct(self, pole); + wcmdname = ole_vstr2wc(method); + hr = pole->pDispatch->lpVtbl->GetIDsOfNames( pole->pDispatch, &IID_NULL, + &wcmdname, 1, cWIN32OLE_lcid, &DispID); + SysFreeString(wcmdname); + return SUCCEEDED(hr) ? Qtrue : Qfalse; +} + static HRESULT ole_docinfo_from_type(ITypeInfo *pTypeInfo, BSTR *name, BSTR *helpstr, DWORD *helpcontext, BSTR *helpfile) { @@ -5728,7 +5759,7 @@ } static VALUE -ole_type_impl_ole_types(ITypeInfo *pTypeInfo) +ole_type_impl_ole_types(ITypeInfo *pTypeInfo, int implflags) { HRESULT hr; ITypeInfo *pRefTypeInfo; @@ -5754,9 +5785,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); @@ -5779,10 +5813,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"); @@ -7536,20 +7623,27 @@ 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); @@ -8281,7 +8375,6 @@ message_filter.MessagePending = mf_MessagePending; com_hash = Data_Wrap_Struct(rb_cData, rb_mark_hash, st_free_table, st_init_numtable()); - com_hash = Data_Wrap_Struct(rb_cData, rb_mark_hash, st_free_table, st_init_numtable()); rb_register_mark_object(com_hash); cWIN32OLE = rb_define_class("WIN32OLE", rb_cObject); @@ -8331,6 +8424,7 @@ rb_define_alias(cWIN32OLE, "ole_obj_help", "ole_type"); rb_define_method(cWIN32OLE, "ole_typelib", fole_typelib, 0); rb_define_method(cWIN32OLE, "ole_query_interface", fole_query_interface, 1); + rb_define_method(cWIN32OLE, "ole_respond_to?", fole_respond_to, 1); rb_define_const(cWIN32OLE, "VERSION", rb_str_new2(WIN32OLE_VERSION)); rb_define_const(cWIN32OLE, "ARGV", rb_ary_new()); @@ -8415,6 +8509,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: win32-unicode-test/ext/json/ext/generator/generator.c =================================================================== --- win32-unicode-test/ext/json/ext/generator/generator.c (revision 17942) +++ win32-unicode-test/ext/json/ext/generator/generator.c (revision 17943) @@ -6,6 +6,10 @@ #include <string.h> #include <math.h> +#ifdef HAVE_IEEEFP_H +#include <ieeefp.h> +#endif + #define check_max_nesting(state, depth) do { \ long current_nesting = 1 + depth; \ if (state->max_nesting != 0 && current_nesting > state->max_nesting) \ Index: win32-unicode-test/ext/socket/socket.c =================================================================== --- win32-unicode-test/ext/socket/socket.c (revision 17942) +++ win32-unicode-test/ext/socket/socket.c (revision 17943) @@ -102,6 +102,8 @@ #endif #endif +#define BLOCKING_REGION(func, arg) (long)rb_thread_blocking_region((func), (arg), RB_UBF_DFL, 0) + #define INET_CLIENT 0 #define INET_SERVER 1 #define INET_SOCKS 2 @@ -498,37 +500,60 @@ return rb_str_new(buf, len); } +struct send_arg { + int fd, flags; + VALUE mesg; + struct sockaddr *to; + socklen_t tolen; +}; + static VALUE +sendto_blocking(void *data) +{ + struct send_arg *arg = data; + VALUE mesg = arg->mesg; + return (VALUE)sendto(arg->fd, RSTRING_PTR(mesg), RSTRING_LEN(mesg), + arg->flags, arg->to, arg->tolen); +} + +static VALUE +send_blocking(void *data) +{ + struct send_arg *arg = data; + VALUE mesg = arg->mesg; + return (VALUE)send(arg->fd, RSTRING_PTR(mesg), RSTRING_LEN(mesg), + arg->flags); +} + +static VALUE bsock_send(int argc, VALUE *argv, VALUE sock) { - VALUE mesg, to; - VALUE flags; + struct send_arg arg; + VALUE flags, to; rb_io_t *fptr; - int fd, n; + int n; + rb_blocking_function_t *func; rb_secure(4); - rb_scan_args(argc, argv, "21", &mesg, &flags, &to); + rb_scan_args(argc, argv, "21", &arg.mesg, &flags, &to); - StringValue(mesg); - if (!NIL_P(to)) StringValue(to); - GetOpenFile(sock, fptr); - fd = fptr->fd; - rb_thread_fd_writable(fd); - retry: + StringValue(arg.mesg); if (!NIL_P(to)) { - TRAP_BEG; - n = sendto(fd, RSTRING_PTR(mesg), RSTRING_LEN(mesg), NUM2INT(flags), - (struct sockaddr*)RSTRING_PTR(to), RSTRING_LEN(to)); - TRAP_END; + StringValue(to); + to = rb_str_new4(to); + arg.to = (struct sockaddr *)RSTRING_PTR(to); + arg.tolen = RSTRING_LEN(to); + func = sendto_blocking; } else { - TRAP_BEG; - n = send(fd, RSTRING_PTR(mesg), RSTRING_LEN(mesg), NUM2INT(flags)); - TRAP_END; + func = send_blocking; } - if (n < 0) { - if (rb_io_wait_writable(fd)) { - goto retry; + GetOpenFile(sock, fptr); + arg.fd = fptr->fd; + arg.flags = NUM2INT(flags); + while ((n = (int)BLOCKING_REGION(func, &arg)) < 0) { + if (rb_io_wait_writable(arg.fd)) { + continue; } rb_sys_fail("send(2)"); } @@ -572,72 +597,80 @@ RECV_SOCKET /* Socket#recvfrom */ }; +struct recvfrom_arg { + int fd, flags; + VALUE str; + socklen_t alen; + char buf[1024]; +}; + static VALUE +recvfrom_blocking(void *data) +{ + struct recvfrom_arg *arg = data; + return (VALUE)recvfrom(arg->fd, RSTRING_PTR(arg->str), RSTRING_LEN(arg->str), + arg->flags, (struct sockaddr*)arg->buf, &arg->alen); +} + +static VALUE s_recvfrom(VALUE sock, int argc, VALUE *argv, enum sock_recv_type from) { rb_io_t *fptr; - VALUE str; - char buf[1024]; - socklen_t alen = sizeof buf; + VALUE str, klass; + struct recvfrom_arg arg; VALUE len, flg; long buflen; long slen; - int fd, flags; rb_scan_args(argc, argv, "11", &len, &flg); - if (flg == Qnil) flags = 0; - else flags = NUM2INT(flg); + if (flg == Qnil) arg.flags = 0; + else arg.flags = NUM2INT(flg); buflen = NUM2INT(len); GetOpenFile(sock, fptr); if (rb_io_read_pending(fptr)) { rb_raise(rb_eIOError, "recv for buffered IO"); } - fd = fptr->fd; + arg.fd = fptr->fd; + arg.alen = sizeof(arg.buf); - str = rb_tainted_str_new(0, buflen); + arg.str = str = rb_tainted_str_new(0, buflen); + klass = RBASIC(str)->klass; + RBASIC(str)->klass = 0; - retry: - rb_thread_wait_fd(fd); - rb_io_check_closed(fptr); - if (RSTRING_LEN(str) != buflen) { - rb_raise(rb_eRuntimeError, "buffer string modified"); + while (rb_io_check_closed(fptr), + (slen = BLOCKING_REGION(recvfrom_blocking, &arg)) < 0) { + if (RBASIC(str)->klass || RSTRING_LEN(str) != buflen) { + rb_raise(rb_eRuntimeError, "buffer string modified"); + } } - TRAP_BEG; - slen = recvfrom(fd, RSTRING_PTR(str), buflen, flags, (struct sockaddr*)buf, &alen); - TRAP_END; - if (slen < 0) { - if (rb_io_wait_readable(fd)) { - goto retry; - } - rb_sys_fail("recvfrom(2)"); - } + RBASIC(str)->klass = klass; if (slen < RSTRING_LEN(str)) { rb_str_set_len(str, slen); } rb_obj_taint(str); switch (from) { case RECV_RECV: - return (VALUE)str; + return str; case RECV_IP: #if 0 - if (alen != sizeof(struct sockaddr_in)) { + if (arg.alen != sizeof(struct sockaddr_in)) { rb_raise(rb_eTypeError, "sockaddr size differs - should not happen"); } #endif - if (alen && alen != sizeof(buf)) /* OSX doesn't return a from result for connection-oriented sockets */ - return rb_assoc_new(str, ipaddr((struct sockaddr*)buf, fptr->mode & FMODE_NOREVLOOKUP)); + if (arg.alen && arg.alen != sizeof(arg.buf)) /* OSX doesn't return a from result for connection-oriented sockets */ + return rb_assoc_new(str, ipaddr((struct sockaddr*)arg.buf, fptr->mode & FMODE_NOREVLOOKUP)); else return rb_assoc_new(str, Qnil); #ifdef HAVE_SYS_UN_H case RECV_UNIX: - return rb_assoc_new(str, unixaddr((struct sockaddr_un*)buf, alen)); + return rb_assoc_new(str, unixaddr((struct sockaddr_un*)arg.buf, arg.alen)); #endif case RECV_SOCKET: - return rb_assoc_new(str, rb_str_new(buf, alen)); + return rb_assoc_new(str, rb_str_new(arg.buf, arg.alen)); default: rb_bug("s_recvfrom called with bad value"); } @@ -850,7 +883,8 @@ make_inetaddr(INADDR_BROADCAST, hbuf, len); } else if (strlen(name) >= len) { - rb_raise(rb_eArgError, "hostname too long (%d)", strlen(name)); + rb_raise(rb_eArgError, "hostname too long (%"PRIuVALUE")", + (VALUE)strlen(name)); } else { strcpy(hbuf, name); @@ -875,7 +909,8 @@ SafeStringValue(port); serv = RSTRING_PTR(port); if (strlen(serv) >= len) { - rb_raise(rb_eArgError, "service name too long (%d)", strlen(serv)); + rb_raise(rb_eArgError, "service name too long (%"PRIuVALUE")", + (VALUE)strlen(serv)); } strcpy(pbuf, serv); return pbuf; @@ -919,19 +954,20 @@ #if defined(__APPLE__) && defined(__MACH__) { - struct addrinfo *r; - r = res; - while (r) { - if (! r->ai_socktype) r->ai_socktype = hints.ai_socktype; - if (! r->ai_protocol) { - if (r->ai_socktype == SOCK_DGRAM) { - r->ai_protocol = IPPROTO_UDP; - } else if (r->ai_socktype == SOCK_STREAM) { - r->ai_protocol = IPPROTO_TCP; - } - } - r = r->ai_next; - } + struct addrinfo *r; + r = res; + while (r) { + if (! r->ai_socktype) r->ai_socktype = hints.ai_socktype; + if (! r->ai_protocol) { + if (r->ai_socktype == SOCK_DGRAM) { + r->ai_protocol = IPPROTO_UDP; + } + else if (r->ai_socktype == SOCK_STREAM) { + r->ai_protocol = IPPROTO_TCP; + } + } + r = r->ai_next; + } } #endif return res; @@ -1098,49 +1134,48 @@ #define WAIT_IN_PROGRESS 1 #endif +struct connect_arg { + int fd; + const struct sockaddr *sockaddr; + socklen_t len; +}; + +static VALUE +connect_blocking(void *data) +{ + struct connect_arg *arg = data; + return (VALUE)connect(arg->fd, arg->sockaddr, arg->len); +} + +#if defined(SOCKS) && !defined(SOCKS5) +static VALUE +socks_connect_blocking(void *data) +{ + struct connect_arg *arg = data; + return (VALUE)Rconnect(arg->fd, arg->sockaddr, arg->len); +} +#endif + static int -ruby_connect(int fd, struct sockaddr *sockaddr, int len, int socks) +ruby_connect(int fd, const struct sockaddr *sockaddr, int len, int socks) { int status; - int mode; + rb_blocking_function_t *func = connect_blocking; + struct connect_arg arg; #if WAIT_IN_PROGRESS > 0 int wait_in_progress = -1; int sockerr; socklen_t sockerrlen; #endif -#if defined(HAVE_FCNTL) -# if defined(F_GETFL) - mode = fcntl(fd, F_GETFL, 0); -# else - mode = 0; -# endif - -#ifdef O_NDELAY -# define NONBLOCKING O_NDELAY -#else -#ifdef O_NBIO -# define NONBLOCKING O_NBIO -#else -# define NONBLOCKING O_NONBLOCK + arg.fd = fd; + arg.sockaddr = sockaddr; + arg.len = len; +#if defined(SOCKS) && !defined(SOCKS5) + if (socks) func = socks_connect_blocking; #endif -#endif -#ifdef SOCKS5 - if (!socks) -#endif - fcntl(fd, F_SETFL, mode|NONBLOCKING); -#endif /* HAVE_FCNTL */ - for (;;) { -#if defined(SOCKS) && !defined(SOCKS5) - if (socks) { - status = Rconnect(fd, sockaddr, len); - } - else -#endif - { - status = connect(fd, sockaddr, len); - } + status = (int)BLOCKING_REGION(func, &arg); if (status < 0) { switch (errno) { case EAGAIN: @@ -1201,9 +1236,6 @@ break; } } -#ifdef HAVE_FCNTL - fcntl(fd, F_SETFL, mode); -#endif return status; } } @@ -1242,7 +1274,7 @@ int type = arg->type; struct addrinfo *res; int fd, status = 0; - const char *syscall; + const char *syscall = 0; arg->remote.res = sock_addrinfo(arg->remote.host, arg->remote.serv, SOCK_STREAM, (type == INET_SERVER) ? AI_PASSIVE : 0); @@ -1493,22 +1525,32 @@ return init_sock(rb_obj_alloc(klass), fd2); } +struct accept_arg { + int fd; + struct sockaddr *sockaddr; + socklen_t *len; +}; + static VALUE +accept_blocking(void *data) +{ + struct accept_arg *arg = data; + return (VALUE)accept(arg->fd, arg->sockaddr, arg->len); +} + +static VALUE s_accept(VALUE klass, int fd, struct sockaddr *sockaddr, socklen_t *len) { int fd2; int retry = 0; + struct accept_arg arg; rb_secure(3); + arg.fd = fd; + arg.sockaddr = sockaddr; + arg.len = len; retry: - rb_thread_wait_fd(fd); -#if defined(_nec_ews) - fd2 = accept(fd, sockaddr, len); -#else - TRAP_BEG; - fd2 = accept(fd, sockaddr, len); - TRAP_END; -#endif + fd2 = (int)BLOCKING_REGION(accept_blocking, &arg); if (fd2 < 0) { switch (errno) { case EMFILE: @@ -1789,24 +1831,28 @@ static VALUE udp_send(int argc, VALUE *argv, VALUE sock) { - VALUE mesg, flags, host, port; + VALUE flags, host, port; rb_io_t *fptr; int n; struct addrinfo *res0, *res; + struct send_arg arg; if (argc == 2 || argc == 3) { return bsock_send(argc, argv, sock); } rb_secure(4); - rb_scan_args(argc, argv, "4", &mesg, &flags, &host, &port); + rb_scan_args(argc, argv, "4", &arg.mesg, &flags, &host, &port); - StringValue(mesg); + StringValue(arg.mesg); res0 = sock_addrinfo(host, port, SOCK_DGRAM, 0); GetOpenFile(sock, fptr); + arg.fd = fptr->fd; + arg.flags = NUM2INT(flags); for (res = res0; res; res = res->ai_next) { retry: - n = sendto(fptr->fd, RSTRING_PTR(mesg), RSTRING_LEN(mesg), NUM2INT(flags), - res->ai_addr, res->ai_addrlen); + arg.to = res->ai_addr; + arg.tolen = res->ai_addrlen; + n = (int)BLOCKING_REGION(sendto_blocking, &arg); if (n >= 0) { freeaddrinfo(res0); return INT2FIX(n); @@ -1922,13 +1968,25 @@ #define FD_PASSING_BY_MSG_ACCRIGHTS 0 #endif +struct iomsg_arg { + int fd; + struct msghdr msg; +}; + static VALUE +sendmsg_blocking(void *data) +{ + struct iomsg_arg *arg = data; + return sendmsg(arg->fd, &arg->msg, 0); +} + +static VALUE unix_send_io(VALUE sock, VALUE val) { #if defined(HAVE_SENDMSG) && (FD_PASSING_BY_MSG_CONTROL || FD_PASSING_BY_MSG_ACCRIGHTS) int fd; rb_io_t *fptr; - struct msghdr msg; + struct iomsg_arg arg; struct iovec vec[1]; char buf[1]; @@ -1953,31 +2011,32 @@ GetOpenFile(sock, fptr); - msg.msg_name = NULL; - msg.msg_namelen = 0; + arg.msg.msg_name = NULL; + arg.msg.msg_namelen = 0; /* Linux and Solaris doesn't work if msg_iov is NULL. */ buf[0] = '\0'; vec[0].iov_base = buf; vec[0].iov_len = 1; - msg.msg_iov = vec; - msg.msg_iovlen = 1; + arg.msg.msg_iov = vec; + arg.msg.msg_iovlen = 1; #if FD_PASSING_BY_MSG_CONTROL - msg.msg_control = (caddr_t)&cmsg; - msg.msg_controllen = CMSG_LEN(sizeof(int)); - msg.msg_flags = 0; + arg.msg.msg_control = (caddr_t)&cmsg; + arg.msg.msg_controllen = CMSG_LEN(sizeof(int)); + arg.msg.msg_flags = 0; MEMZERO((char*)&cmsg, char, sizeof(cmsg)); cmsg.hdr.cmsg_len = CMSG_LEN(sizeof(int)); cmsg.hdr.cmsg_level = SOL_SOCKET; cmsg.hdr.cmsg_type = SCM_RIGHTS; *(int *)CMSG_DATA(&cmsg.hdr) = fd; #else - msg.msg_accrights = (caddr_t)&fd; - msg.msg_accrightslen = sizeof(fd); + arg.msg.msg_accrights = (caddr_t)&fd; + arg.msg.msg_accrightslen = sizeof(fd); #endif - if (sendmsg(fptr->fd, &msg, 0) == -1) + arg.fd = fptr->fd; + if ((int)BLOCKING_REGION(sendmsg_blocking, &arg) == -1) rb_sys_fail("sendmsg(2)"); return Qnil; @@ -1988,12 +2047,19 @@ } static VALUE +recvmsg_blocking(void *data) +{ + struct iomsg_arg *arg = data; + return recvmsg(arg->fd, &arg->msg, 0); +} + +static VALUE unix_recv_io(int argc, VALUE *argv, VALUE sock) { #if defined(HAVE_RECVMSG) && (FD_PASSING_BY_MSG_CONTROL || FD_PASSING_BY_MSG_ACCRIGHTS) VALUE klass, mode; rb_io_t *fptr; - struct msghdr msg; + struct iomsg_arg arg; struct iovec vec[2]; char buf[1]; @@ -2013,59 +2079,58 @@ GetOpenFile(sock, fptr); - rb_io_wait_readable(fptr->fd); + arg.msg.msg_name = NULL; + arg.msg.msg_namelen = 0; - msg.msg_name = NULL; - msg.msg_namelen = 0; - vec[0].iov_base = buf; vec[0].iov_len = sizeof(buf); - msg.msg_iov = vec; - msg.msg_iovlen = 1; + arg.msg.msg_iov = vec; + arg.msg.msg_iovlen = 1; #if FD_PASSING_BY_MSG_CONTROL - msg.msg_control = (caddr_t)&cmsg; - msg.msg_controllen = CMSG_SPACE(sizeof(int)); - msg.msg_flags = 0; + arg.msg.msg_control = (caddr_t)&cmsg; + arg.msg.msg_controllen = CMSG_SPACE(sizeof(int)); + arg.msg.msg_flags = 0; cmsg.hdr.cmsg_len = CMSG_LEN(sizeof(int)); cmsg.hdr.cmsg_level = SOL_SOCKET; cmsg.hdr.cmsg_type = SCM_RIGHTS; *(int *)CMSG_DATA(&cmsg.hdr) = -1; #else - msg.msg_accrights = (caddr_t)&fd; - msg.msg_accrightslen = sizeof(fd); + arg.msg.msg_accrights = (caddr_t)&fd; + arg.msg.msg_accrightslen = sizeof(fd); fd = -1; #endif - if (recvmsg(fptr->fd, &msg, 0) == -1) + arg.fd = fptr->fd; + if ((int)BLOCKING_REGION(recvmsg_blocking, &arg) == -1) rb_sys_fail("recvmsg(2)"); #if FD_PASSING_BY_MSG_CONTROL - if (msg.msg_controllen != CMSG_SPACE(sizeof(int))) { - rb_raise(rb_eSocket, - "file descriptor was not passed (msg_controllen=%d, %d expected)", - msg.msg_controllen, CMSG_SPACE(sizeof(int))); + if (arg.msg.msg_controllen != CMSG_SPACE(sizeof(int))) { + rb_raise(rb_eSocket, + "file descriptor was not passed (msg_controllen=%d, %d expected)", + (int)arg.msg.msg_controllen, (int)CMSG_SPACE(sizeof(int))); } if (cmsg.hdr.cmsg_len != CMSG_LEN(sizeof(int))) { - rb_raise(rb_eSocket, - "file descriptor was not passed (cmsg_len=%d, %d expected)", - cmsg.hdr.cmsg_len, CMSG_LEN(sizeof(int))); + rb_raise(rb_eSocket, + "file descriptor was not passed (cmsg_len=%d, %d expected)", + (int)cmsg.hdr.cmsg_len, (int)CMSG_LEN(sizeof(int))); } if (cmsg.hdr.cmsg_level != SOL_SOCKET) { - rb_raise(rb_eSocket, - "file descriptor was not passed (cmsg_level=%d, %d expected)", - cmsg.hdr.cmsg_level, SOL_SOCKET); + rb_raise(rb_eSocket, + "file descriptor was not passed (cmsg_level=%d, %d expected)", + cmsg.hdr.cmsg_level, SOL_SOCKET); } if (cmsg.hdr.cmsg_type != SCM_RIGHTS) { - rb_raise(rb_eSocket, - "file descriptor was not passed (cmsg_type=%d, %d expected)", - cmsg.hdr.cmsg_type, SCM_RIGHTS); + rb_raise(rb_eSocket, + "file descriptor was not passed (cmsg_type=%d, %d expected)", + cmsg.hdr.cmsg_type, SCM_RIGHTS); } #else - if (msg.msg_accrightslen != sizeof(fd)) { + if (arg.msg.msg_accrightslen != sizeof(fd)) { rb_raise(rb_eSocket, - "file descriptor was not passed (accrightslen) : %d != %d", - msg.msg_accrightslen, sizeof(fd)); + "file descriptor was not passed (accrightslen) : %d != %d", + arg.msg.msg_accrightslen, (int)sizeof(fd)); } #endif @@ -3474,7 +3539,7 @@ } if (sizeof(struct sockaddr_un) < RSTRING_LEN(addr)) { rb_raise(rb_eTypeError, "too long sockaddr_un - %ld longer than %d", - RSTRING_LEN(addr), sizeof(struct sockaddr_un)); + RSTRING_LEN(addr), (int)sizeof(struct sockaddr_un)); } sun_path = unixpath(sockaddr, RSTRING_LEN(addr)); if (sizeof(struct sockaddr_un) == RSTRING_LEN(addr) && Index: win32-unicode-test/numeric.c =================================================================== --- win32-unicode-test/numeric.c (revision 17942) +++ win32-unicode-test/numeric.c (revision 17943) @@ -1615,9 +1615,10 @@ { unsigned long num = rb_num2ulong(val); - if (RTEST(rb_funcall(INT2FIX(0), '<', 1, val))) { + if (RTEST(rb_funcall(val, '<', 1, INT2FIX(0)))) + check_int(num); + else check_uint(num); - } return num; } @@ -1630,9 +1631,10 @@ return rb_num2uint(val); } num = FIX2ULONG(val); - if (FIX2LONG(val) > 0) { + if (RTEST(rb_funcall(val, '<', 1, INT2FIX(0)))) + check_int(num); + else check_uint(num); - } return num; } #else Index: win32-unicode-test/vm.c =================================================================== --- win32-unicode-test/vm.c (revision 17942) +++ win32-unicode-test/vm.c (revision 17943) @@ -1395,6 +1395,7 @@ RUBY_MARK_UNLESS_NULL(vm->load_path); RUBY_MARK_UNLESS_NULL(vm->loaded_features); RUBY_MARK_UNLESS_NULL(vm->top_self); + RUBY_MARK_UNLESS_NULL(vm->coverages); rb_gc_mark_locations(vm->special_exceptions, vm->special_exceptions + ruby_special_error_count - 1); if (vm->loading_table) { @@ -1908,3 +1909,9 @@ { return ruby_vm_debug_ptr(GET_VM()); } + +VALUE +rb_vm_get_coverages(void) +{ + return GET_VM()->coverages; +} Index: win32-unicode-test/version.h =================================================================== --- win32-unicode-test/version.h (revision 17942) +++ win32-unicode-test/version.h (revision 17943) @@ -1,7 +1,7 @@ #define RUBY_VERSION "1.9.0" -#define RUBY_RELEASE_DATE "2008-07-03" +#define RUBY_RELEASE_DATE "2008-07-07" #define RUBY_VERSION_CODE 190 -#define RUBY_RELEASE_CODE 20080703 +#define RUBY_RELEASE_CODE 20080707 #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 3 +#define RUBY_RELEASE_DAY 7 #ifdef RUBY_EXTERN RUBY_EXTERN const char ruby_version[]; Index: win32-unicode-test/test/ruby/test_m17n.rb =================================================================== --- win32-unicode-test/test/ruby/test_m17n.rb (revision 17942) +++ win32-unicode-test/test/ruby/test_m17n.rb (revision 17943) @@ -493,6 +493,33 @@ assert_match(/[[:space:]]/, "\u{00a0}") end + def test_regexp_property + s = '\p{Hiragana}'.force_encoding("euc-jp") + assert_equal(Encoding::EUC_JP, s.encoding) + r = nil + assert_nothing_raised { + r = Regexp.new(s) + } + assert(r.fixed_encoding?) + assert_match(r, "\xa4\xa2".force_encoding("euc-jp")) + + r = eval('/\p{Hiragana}/'.force_encoding("euc-jp")) + assert(r.fixed_encoding?) + assert_match(r, "\xa4\xa2".force_encoding("euc-jp")) + + r = /\p{Hiragana}/e + assert(r.fixed_encoding?) + assert_match(r, "\xa4\xa2".force_encoding("euc-jp")) + + r = eval('/\u{3042}\p{Hiragana}/'.force_encoding("euc-jp")) + assert(r.fixed_encoding?) + assert_equal(Encoding::UTF_8, r.encoding) + + r = eval('/\p{Hiragana}\u{3042}/'.force_encoding("euc-jp")) + assert(r.fixed_encoding?) + assert_equal(Encoding::UTF_8, r.encoding) + end + def test_regexp_embed_preprocess r1 = /\xa4\xa2/e r2 = /#{r1}/ Index: win32-unicode-test/test/ruby/test_dir.rb =================================================================== --- win32-unicode-test/test/ruby/test_dir.rb (revision 17942) +++ win32-unicode-test/test/ruby/test_dir.rb (revision 17943) @@ -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: win32-unicode-test/test/ruby/test_m17n_comb.rb =================================================================== --- win32-unicode-test/test/ruby/test_m17n_comb.rb (revision 17942) +++ win32-unicode-test/test/ruby/test_m17n_comb.rb (revision 17943) @@ -1122,6 +1122,8 @@ def test_str_slice! each_slice_call {|s, *args| + desc_slice = "#{encdump s}.slice#{encdumpargs args}" + desc_slice_bang = "#{encdump s}.slice!#{encdumpargs args}" t = s.dup begin r = t.slice!(*args) @@ -1129,14 +1131,14 @@ e = $! end if e - assert_raise(e.class, "#{encdump s}.slice#{encdumpargs args}") { s.slice(*args) } + assert_raise(e.class, desc_slice) { s.slice(*args) } next end if !r - assert_nil(s.slice(*args)) + assert_nil(s.slice(*args), desc_slice) next end - assert_equal(s.slice(*args), r) + assert_equal(s.slice(*args), r, desc_slice_bang) assert_equal(s.bytesize, r.bytesize + t.bytesize) if args.length == 1 && String === args[0] assert_equal(args[0].encoding, r.encoding, Index: win32-unicode-test/test/win32ole/test_win32ole.rb =================================================================== --- win32-unicode-test/test/win32ole/test_win32ole.rb (revision 17942) +++ win32-unicode-test/test/win32ole/test_win32ole.rb (revision 17943) @@ -246,6 +246,16 @@ assert_instance_of(WIN32OLE, shell2) end + def test_ole_respond_to + fso = WIN32OLE.new('Scripting.FileSystemObject') + assert(fso.ole_respond_to?('getFolder')) + assert(fso.ole_respond_to?('GETFOLDER')) + assert(!fso.ole_respond_to?('XXXXX')) + assert_raise(TypeError) { + assert_raise(fso.ole_respond_to?(1)) + } + end + def test_s_const_load assert(!defined?(CONST1::SsfWINDOWS)) shell=WIN32OLE.new('Shell.Application') Index: win32-unicode-test/test/win32ole/test_win32ole_type.rb =================================================================== --- win32-unicode-test/test/win32ole/test_win32ole_type.rb (revision 17942) +++ win32-unicode-test/test/win32ole/test_win32ole_type.rb (revision 17943) @@ -30,7 +30,22 @@ } ole_type = WIN32OLE_TYPE.new("Microsoft Shell Controls And Automation", "Shell") assert_instance_of(WIN32OLE_TYPE, ole_type) - + assert_equal("Shell", ole_type.name) + assert_equal("Class", ole_type.ole_type) + assert_equal("{13709620-C279-11CE-A49E-444553540000}", ole_type.guid) + assert_equal("Shell.Application.1", ole_type.progid) + assert_equal(true, ole_type.visible?) + assert_equal("Shell", ole_type.to_s) + assert_equal(0, ole_type.major_version) + assert_equal(0, ole_type.minor_version) + assert_equal(5, ole_type.typekind) + assert_equal("Shell Object Type Information", ole_type.helpstring) + assert_equal(nil, ole_type.src_type) + assert_equal("", ole_type.helpfile) + assert_equal(0, ole_type.helpcontext) + assert_equal([], ole_type.variables) + assert(ole_type.ole_methods.select{|m|/NameSpace/i =~ m.name}.size > 0) + ole_type2 = WIN32OLE_TYPE.new("{13709620-C279-11CE-A49E-444553540000}", "Shell") assert_instance_of(WIN32OLE_TYPE, ole_type) assert_equal(ole_type.name, ole_type2.name) @@ -151,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 Index: win32-unicode-test/test/win32ole/test_win32ole_variant.rb =================================================================== --- win32-unicode-test/test/win32ole/test_win32ole_variant.rb (revision 17942) +++ win32-unicode-test/test/win32ole/test_win32ole_variant.rb (revision 17943) @@ -540,6 +540,44 @@ } end + def test_conversion_vt_date + obj = WIN32OLE_VARIANT.new(-657434, WIN32OLE::VARIANT::VT_DATE) + assert_equal("0100/01/01 00:00:00", obj.value) + + obj = WIN32OLE_VARIANT.new("1500/12/29 23:59:59", WIN32OLE::VARIANT::VT_DATE) + assert_equal("1500/12/29 23:59:59", obj.value) + + obj = WIN32OLE_VARIANT.new("1500/12/30 00:00:00", WIN32OLE::VARIANT::VT_DATE) + assert_equal("1500/12/30 00:00:00", obj.value) + + obj = WIN32OLE_VARIANT.new("1500/12/30 00:00:01", WIN32OLE::VARIANT::VT_DATE) + assert_equal("1500/12/30 00:00:01", obj.value) + + obj = WIN32OLE_VARIANT.new("1899/12/29 23:59:59", WIN32OLE::VARIANT::VT_DATE) + assert_equal("1899/12/29 23:59:59", obj.value) + + obj = WIN32OLE_VARIANT.new("1899/12/30 00:00:00", WIN32OLE::VARIANT::VT_DATE) + assert_equal("1899/12/30 00:00:00", obj.value) + + obj = WIN32OLE_VARIANT.new("1899/12/30 00:00:01", WIN32OLE::VARIANT::VT_DATE) + assert_equal("1899/12/30 00:00:01", obj.value) + + obj = WIN32OLE_VARIANT.new(0, WIN32OLE::VARIANT::VT_DATE) + assert_equal("1899/12/30 00:00:00", obj.value) + + obj = WIN32OLE_VARIANT.new("2008/12/29 23:59:59", WIN32OLE::VARIANT::VT_DATE) + assert_equal("2008/12/29 23:59:59", obj.value) + + obj = WIN32OLE_VARIANT.new("2008/12/30 00:00:00", WIN32OLE::VARIANT::VT_DATE) + assert_equal("2008/12/30 00:00:00", obj.value) + + obj = WIN32OLE_VARIANT.new("2008/12/30 00:00:01", WIN32OLE::VARIANT::VT_DATE) + assert_equal("2008/12/30 00:00:01", obj.value) + + obj = WIN32OLE_VARIANT.new("9999/12/31 23:59:59", WIN32OLE::VARIANT::VT_DATE) + assert_equal("9999/12/31 23:59:59", obj.value) + end + def test_create_nil_dispatch var = WIN32OLE_VARIANT.new(nil, WIN32OLE::VARIANT::VT_DISPATCH) assert_nil(var.value) Index: win32-unicode-test/test/win32ole/test_word.rb =================================================================== --- win32-unicode-test/test/win32ole/test_word.rb (revision 17942) +++ win32-unicode-test/test/win32ole/test_word.rb (revision 17943) @@ -7,39 +7,66 @@ end require "test/unit" -if defined?(WIN32OLE) - class TestWIN32OLE_WITH_WORD < Test::Unit::TestCase - - def setup - begin - @obj = WIN32OLE.new('Word.Application') - rescue WIN32OLERuntimeError - @obj = nil +def word_installed? + installed = false + w = nil + if defined?(WIN32OLE) + begin + w = WIN32OLE.new('Word.Application') + installed = true + rescue + ensure + if w + w.quit + w = nil end end + end + return installed +end - def test_ole_methods - if @obj - @obj.visible = true - @obj.wordbasic.disableAutoMacros(true) - assert(true) +if defined?(WIN32OLE) + w = nil + dotest = word_installed? + if !dotest + STDERR.puts("\n#{__FILE__} skipped(Microsoft Word not found.)") + end + if dotest + class TestWIN32OLE_WITH_WORD < Test::Unit::TestCase + def setup + begin + @obj = WIN32OLE.new('Word.Application') + rescue WIN32OLERuntimeError + @obj = nil + if !$skipped + $skipped = true + end + end end - end - def test_s_connect - if @obj - obj2 = WIN32OLE.connect("Word.Application") - assert_instance_of(WIN32OLE, obj2) - obj2.visible = true + def test_ole_methods + if @obj + @obj.visible = true + @obj.wordbasic.disableAutoMacros(true) + assert(true) + else + end end - end - def teardown - if @obj - @obj.quit - @obj = nil + def test_s_connect + if @obj + obj2 = WIN32OLE.connect("Word.Application") + assert_instance_of(WIN32OLE, obj2) + obj2.visible = true + end end + + def teardown + if @obj + @obj.quit + @obj = nil + end + end end - end end Index: win32-unicode-test/test/test_singleton.rb =================================================================== --- win32-unicode-test/test/test_singleton.rb (revision 0) +++ win32-unicode-test/test/test_singleton.rb (revision 17943) @@ -0,0 +1,15 @@ +require 'test/unit' +require 'singleton' + +class TestSingleton < Test::Unit::TestCase + class C + include Singleton + end + + def test_marshal + o1 = C.instance + m = Marshal.dump(o1) + o2 = Marshal.load(m) + assert_same(o1, o2) + end +end Property changes on: win32-unicode-test/test/test_singleton.rb ___________________________________________________________________ Name: svn:eol-style + LF Index: win32-unicode-test/rational.c =================================================================== --- win32-unicode-test/rational.c (revision 17942) +++ win32-unicode-test/rational.c (revision 17943) @@ -12,6 +12,10 @@ #define NDEBUG #include <assert.h> +#ifdef HAVE_IEEEFP_H +#include <ieeefp.h> +#endif + #ifndef RATIONAL_NAME #define RATIONAL_NAME "Rational" #endif Index: win32-unicode-test/file.c =================================================================== --- win32-unicode-test/file.c (revision 17942) +++ win32-unicode-test/file.c (revision 17943) @@ -3123,7 +3123,7 @@ p = last; break; } - e = dot; + if (*last == '.') e = dot; continue; #else e = p; /* get the last dot of the last component */ Index: win32-unicode-test/missing/tgamma.c =================================================================== --- win32-unicode-test/missing/tgamma.c (revision 17942) +++ win32-unicode-test/missing/tgamma.c (revision 17943) @@ -24,7 +24,6 @@ return 1/x < 0 ? -HUGE_VAL : HUGE_VAL; } if (x < 0) { - int sign; static double zero = 0.0; double i, f; f = modf(-x, &i); -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/