diff options
author | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2008-11-27 07:42:55 +0000 |
---|---|---|
committer | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2008-11-27 07:42:55 +0000 |
commit | 74ba517411b5926b1da584f921daf03ff8a72ec4 (patch) | |
tree | 6fc8090140e2f30685e4d720ca400ce6cda61f61 | |
parent | 652f15029b099ebae0cfb89f5adc435faeb5fb09 (diff) | |
download | ruby-74ba517411b5926b1da584f921daf03ff8a72ec4.tar.gz |
* merged from trunk r20281:20375.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/mvm@20376 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
41 files changed, 931 insertions, 287 deletions
diff --git a/.merged-trunk-revision b/.merged-trunk-revision index c20f5c10e4..015035283b 100644 --- a/.merged-trunk-revision +++ b/.merged-trunk-revision @@ -1 +1 @@ -20281 +20375 @@ -1,3 +1,246 @@ +Thu Nov 27 16:32:53 2008 Nobuyoshi Nakada <nobu@ruby-lang.org> + + * signal.c (register_sigaltstack): stores alt stack for debug + purpose. + +Thu Nov 27 16:12:33 2008 Nobuyoshi Nakada <nobu@ruby-lang.org> + + * signal.c (ruby_sigaction_t): added. + +Thu Nov 27 15:59:16 2008 Nobuyoshi Nakada <nobu@ruby-lang.org> + + * gc.c (ruby_stack_check): no check if using sigaltstack. + + * signal.c (ALT_STACK_SIZE): default minimum size is insufficient + for method calls. + + * signal.c (sigsegv): handles stack overflow if possible. + + * thread.c (ruby_thread_stack_overflow): helper function to raise + sysstack_error. + + * thread_pthread.c (ruby_stack_overflowed_p): checks for stack + overflow. + +Thu Nov 27 10:40:52 2008 Yukihiro Matsumoto <matz@ruby-lang.org> + + * ext/bigdecimal/bigdecimal.c (BigDecimal_div2): should return + Integer for #div operation. + + * ext/bigdecimal/bigdecimal.c (BigDecimal_div2): should raise + ZeroDivisionError if divisor is zero. [ruby-dev:37207] + +Wed Nov 26 23:15:47 2008 Yukihiro Matsumoto <matz@ruby-lang.org> + + * strftime.c (STRFTIME): use rb_strftime() recursively, instead of + platform's strftime(). + +Wed Nov 26 22:46:23 2008 Yukihiro Matsumoto <matz@ruby-lang.org> + + * ext/bigdecimal/bigdecimal.c (VpException): bigdecimal zero + division should raise FloatDomainError if mode + VP_EXCEPTION_ZERODIVIDE is set. [ruby-dev:37204] + + * ext/bigdecimal/bigdecimal.c (BigDecimal_mode): should handle + VP_EXCEPTION_ZERODIVIDE. + +Wed Nov 26 15:16:07 2008 Kazuhiro NISHIYAMA <zn@mbf.nifty.com> + + * ext/gdbm/gdbm.c (rb_gdbm_nextkey): fix memory leak. + +Wed Nov 26 03:17:48 2008 Yukihiro Matsumoto <matz@ruby-lang.org> + + * ext/bigdecimal/bigdecimal.c (BigDecimal_to_r): raise exception + for nan/inf conversion. [ruby-dev:37187] fix #793 + + * ext/bigdecimal/bigdecimal.c (BigDecimal_to_i): ditto. + +Wed Nov 26 03:00:59 2008 Yukihiro Matsumoto <matz@ruby-lang.org> + + * ext/bigdecimal/bigdecimal.c (VpAlloc): avoid ALLOCA_N() to avoid + segmentation fault caused by (insanely) long decimal values. + [ruby-dev:37189] fix #794 + + * ext/bigdecimal/bigdecimal.c (BigDecimal_dump, BigDecimal_to_i, + BigDecimal_to_f, BigDecimal_to_s, BigDecimal_split, + BigDecimal_inspect): ditto. + + * ext/bigdecimal/bigdecimal.c (VpToString): small performance + improvement. + +Wed Nov 26 00:26:30 2008 Yukihiro Matsumoto <matz@ruby-lang.org> + + * strftime.c (STRFTIME): should add padding for %[xXrR] etc. + [ruby-dev:37185] fix: #792 + +Tue Nov 25 16:26:12 2008 Yukihiro Matsumoto <matz@ruby-lang.org> + + * array.c (rb_ary_times): taint (and untrust) status should be + inherited by "ary * 0". [ruby-dev:37024] + +Tue Nov 25 15:54:07 2008 Yukihiro Matsumoto <matz@ruby-lang.org> + + * strftime.c (rb_strftime): should not swallow incomplete + formatter, e.g. "%E". [ruby-dev:37170] fix: #787 + + * strftime.c (rb_strftime): clear flags before processing unknown + formatter, e.g. "%i". [ruby-dev:37180] + +Tue Nov 25 10:35:29 2008 Yukihiro Matsumoto <matz@ruby-lang.org> + + * strftime.c (rb_strftime): "%^P" should convert to upper case. + [ruby-dev:37180] + +Tue Nov 25 07:51:18 2008 Yukihiro Matsumoto <matz@ruby-lang.org> + + * strftime.c (FMT): use "%0d" formatter for zero padding, not "%.d". + [ruby-dev:37168] fix: #768 + + * strftime.c (rb_strftime): %s to use zero padding by default. + [ruby-dev:37180] + +Tue Nov 25 03:37:42 2008 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp> + + * ext/tk/lib/tkextlib/blt/tabset.rb, + ext/tk/lib/tkextlib/blt/tabnotebook.rb: + fix many bugs. Now, those work properly. + +Tue Nov 25 03:26:04 2008 Yukihiro Matsumoto <matz@ruby-lang.org> + + * numeric.c (num_step): treat infinite step specially. + [ruby-dev:37157] fix: #781. + +Tue Nov 25 01:23:25 2008 Tadayoshi Funaba <tadf@dotrb.org> + + * lib/date/format.rb (strftime): ignores '_' flag for %[LN]. + +Tue Nov 25 00:08:22 2008 Nobuyoshi Nakada <nobu@ruby-lang.org> + + * process.c (rb_fork): stops the timer thread during fork. + [ruby-dev:37117] + + * thread.c (rb_thread_start_timer_thread): timer thread needs + system_working to be set. + +Mon Nov 24 23:27:28 2008 Shugo Maeda <shugo@ruby-lang.org> + + * strftime.c (rb_strftime): The # flag should work with %a, %A, %b, + %B, and %h. [ruby-dev:37162] + + * test/ruby/test_time.rb (test_strftime): ditto. + +Mon Nov 24 23:16:32 2008 Yukihiro Matsumoto <matz@ruby-lang.org> + + * signal.c (register_sigaltstack): should not add external + variable (with some cosmetic changes). [ruby-dev:37158] + +Mon Nov 24 22:57:25 2008 Shugo Maeda <shugo@ruby-lang.org> + + * strftime.c (rb_strftime): A width specifier for %t and %n should + work. [ruby-dev:37160] + + * test/ruby/test_time.rb (test_strftime): ditto. + +Mon Nov 24 22:07:07 2008 Shugo Maeda <shugo@ruby-lang.org> + + * strftime.c (rb_strftime): The precision of %0N should be 9. + [ruby-dev:37156] + + * test/ruby/test_time.rb (test_strftime): ditto. + +Mon Nov 24 21:38:23 2008 Shugo Maeda <shugo@ruby-lang.org> + + * strftime.c (rb_strftime): The default precision should be 1, not + 0. [ruby-dev:37155] + + * test/ruby/test_time.rb (test_strftime): ditto. + +Mon Nov 24 19:53:47 2008 Tadayoshi Funaba <tadf@dotrb.org> + + * lib/date.rb (inspect): changed again. + +Mon Nov 24 18:35:00 2008 Yukihiro Matsumoto <matz@ruby-lang.org> + + * lib/time.rb: r20251 reverted. The patched behavior do not round + trip. [ruby-core:19988] + +Sun Nov 23 16:04:05 2008 Yuki Sonoda (Yugui) <yugui@yugui.jp> + + * signal.c (default_handler, Init_signal): compile error if + USE_SIGALTSTACK is not defined. + +Sun Nov 23 00:04:14 2008 Yuki Sonoda (Yugui) <yugui@yugui.jp> + + * signal.c (ALT_STACK_SIZE): 4KB is not enough on Mac OS X. + Uses SIGSTKSZ. + +Sat Nov 22 21:29:54 2008 Yuki Sonoda (Yugui) <yugui@yugui.jp> + + * test/ruby/test_method.rb (test_default_accessiblity): test case for + [ruby-dev:37124]. + +Sat Nov 22 18:24:24 2008 Yukihiro Matsumoto <matz@ruby-lang.org> + + * file.c (rb_file_world_writable_p): should return nil for non + world-writable files. + +Sat Nov 22 10:31:25 2008 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp> + + * ext/tk/lib/tkextlib/blt.rb, ext/tk/lib/tkextlib/blt/vector.rb: + fix NameError bug. + +Sat Nov 22 03:41:22 2008 Yukihiro Matsumoto <matz@ruby-lang.org> + + * ext/pty/pty.c (get_device_once): abandon asynchronous exception + that might cause serious problem if a program terminated early. + asynchronous exception is a very bad thing anyway. use + Process.waitpid(pid) or PTY.check(pid) to poll program + termination. if PTY.check is called with optional second + argument being true, it raises an exception same as one from + previous behavior. [incompatible] fix: [ruby-core:19583] + +Fri Nov 21 22:24:31 2008 Yukihiro Matsumoto <matz@ruby-lang.org> + + * ext/curses/curses.c (curses_escdelay_set): support ESCDELAY. a + patch from Giancarlo F Bellido <support at coaxialhost.com> in + [ruby-core:19961]. + +Fri Nov 21 22:17:15 2008 Yukihiro Matsumoto <matz@ruby-lang.org> + + * ruby.c (usage): -W description updated. [ruby-core:19858] + +Fri Nov 21 21:50:54 2008 Yukihiro Matsumoto <matz@ruby-lang.org> + + * signal.c (register_sigaltstack): use alternative stack for + SIGSEGV to avoid uncaught stack overflow. based on a patch from + Hiro Yoshioka <hyoshiok at miraclelinux.com> in [ruby-dev:37134]. + [ruby-dev:36993] + +Fri Nov 21 16:06:54 2008 Yukihiro Matsumoto <matz@ruby-lang.org> + + * vm.c (thread_free): th->vm may be NULL when pthread_create + failed for ENOMEM. [ruby-dev:37095] + +Thu Nov 20 07:33:15 2008 Yukihiro Matsumoto <matz@ruby-lang.org> + + * lib/logger.rb (Logger): should handle the case that cvs/svn do + not expand $Id keyword. [ruby-core:19991] + +Thu Nov 20 07:27:36 2008 Yukihiro Matsumoto <matz@ruby-lang.org> + + * lib/minitest/unit.rb (MiniTest::Assertions#capture_io): adjust + indentation to shut up warning. [ruby-core:19993] + +Wed Nov 19 17:48:05 2008 Yukihiro Matsumoto <matz@ruby-lang.org> + + * ext/syck/rubyext.c (rb_syck_mktime): return DateTime for a value + out of range of Time. [ruby-core:19919] + +Wed Nov 19 14:14:38 2008 Yukihiro Matsumoto <matz@ruby-lang.org> + + * node.h (NOEX_MODFUNC): should be include NOEX_PRIVATE. + [ruby-dev:37124] + Wed Nov 19 03:01:04 2008 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp> * test/rinda/test_rinda.rb: fixed fails occasionally [ruby-dev:37119]. @@ -2549,7 +2549,10 @@ rb_ary_times(VALUE ary, VALUE times) } len = NUM2LONG(times); - if (len == 0) return ary_new(rb_obj_class(ary), 0); + if (len == 0) { + ary2 = ary_new(rb_obj_class(ary), 0); + goto out; + } if (len < 0) { rb_raise(rb_eArgError, "negative argument"); } @@ -2564,6 +2567,7 @@ rb_ary_times(VALUE ary, VALUE times) for (i=0; i<len; i+=RARRAY_LEN(ary)) { MEMCPY(RARRAY_PTR(ary2)+i, RARRAY_PTR(ary), VALUE, RARRAY_LEN(ary)); } + out: OBJ_INFECT(ary2, ary); return ary2; diff --git a/configure.in b/configure.in index ef782295e1..771973d037 100644 --- a/configure.in +++ b/configure.in @@ -789,7 +789,7 @@ AC_CHECK_FUNCS(fmod killpg wait4 waitpid fork spawnv syscall chroot fsync getcwd setsid telldir seekdir fchmod cosh sinh tanh log2 round signbit\ setuid setgid daemon select_large_fdset setenv unsetenv\ mktime timegm gmtime_r clock_gettime gettimeofday\ - pread sendfile shutdown) + pread sendfile shutdown sigaltstack) AC_CACHE_CHECK(for __builtin_setjmp, ac_cv_func___builtin_setjmp, [AC_TRY_LINK([@%:@include <setjmp.h> @@ -1157,7 +1157,6 @@ if test x"$enable_pthread" = xyes; then AC_MSG_WARN("Don't know how to find pthread library on your system -- thread support disabled") fi AC_CHECK_FUNCS(nanosleep sched_yield pthread_attr_setinheritsched) - AC_CHECK_FUNCS(sigaltstack) AC_CHECK_FUNCS(pthread_getattr_np pthread_attr_getstack) AC_CHECK_FUNCS(pthread_attr_get_np) AC_CHECK_FUNCS(pthread_get_stackaddr_np pthread_get_stacksize_np) diff --git a/ext/bigdecimal/bigdecimal.c b/ext/bigdecimal/bigdecimal.c index 96bd88160c..62ff80a860 100644 --- a/ext/bigdecimal/bigdecimal.c +++ b/ext/bigdecimal/bigdecimal.c @@ -309,17 +309,19 @@ static VALUE BigDecimal_dump(int argc, VALUE *argv, VALUE self) { ENTER(5); - char sz[50]; Real *vp; char *psz; VALUE dummy; + volatile VALUE dump; + rb_scan_args(argc, argv, "01", &dummy); GUARD_OBJ(vp,GetVpValue(self,1)); - sprintf(sz,"%lu:",VpMaxPrec(vp)*VpBaseFig()); - psz = ALLOCA_N(char,(unsigned int)VpNumOfChars(vp,"E")+strlen(sz)); - sprintf(psz,"%s",sz); + dump = rb_str_new(0,VpNumOfChars(vp,"E")+50); + psz = RSTRING_PTR(dump); + sprintf(psz,"%lu:",VpMaxPrec(vp)*VpBaseFig()); VpToString(vp, psz+strlen(psz), 0, 0); - return rb_str_new2(psz); + rb_str_resize(dump, strlen(psz)); + return dump; } /* @@ -423,6 +425,11 @@ BigDecimal_mode(int argc, VALUE *argv, VALUE self) (fo&(~VP_EXCEPTION_UNDERFLOW)))); } fo = VpGetException(); + if(f&VP_EXCEPTION_ZERODIVIDE) { + VpSetException((unsigned short)((val==Qtrue)?(fo|VP_EXCEPTION_ZERODIVIDE): + (fo&(~VP_EXCEPTION_ZERODIVIDE)))); + } + fo = VpGetException(); return INT2FIX(fo); } if(VP_ROUND_MODE==f) { @@ -519,6 +526,18 @@ BigDecimal_IsFinite(VALUE self) return Qtrue; } +static void +BigDecimal_check_num(Real *p) +{ + if(VpIsNaN(p)) { + VpException(VP_EXCEPTION_NaN,"Computation results to 'NaN'(Not a Number)",1); + } else if(VpIsPosInf(p)) { + VpException(VP_EXCEPTION_INFINITY,"Computation results to 'Infinity'",1); + } else if(VpIsNegInf(p)) { + VpException(VP_EXCEPTION_INFINITY,"Computation results to '-Infinity'",1); + } +} + /* Returns the value as an integer (Fixnum or Bignum). * * If the BigNumber is infinity or NaN, returns nil. @@ -529,22 +548,12 @@ BigDecimal_to_i(VALUE self) ENTER(5); int e,n,i,nf; U_LONG v,b,j; + volatile VALUE str; char *psz,*pch; Real *p; GUARD_OBJ(p,GetVpValue(self,1)); - - /* Infinity or NaN not converted. */ - if(VpIsNaN(p)) { - VpException(VP_EXCEPTION_NaN,"Computation results to 'NaN'(Not a Number)",0); - return Qnil; - } else if(VpIsPosInf(p)) { - VpException(VP_EXCEPTION_INFINITY,"Computation results to 'Infinity'",0); - return Qnil; - } else if(VpIsNegInf(p)) { - VpException(VP_EXCEPTION_INFINITY,"Computation results to '-Infinity'",0); - return Qnil; - } + BigDecimal_check_num(p); e = VpExponent10(p); if(e<=0) return INT2FIX(0); @@ -553,7 +562,8 @@ BigDecimal_to_i(VALUE self) e = VpGetSign(p)*p->frac[0]; return INT2FIX(e); } - psz = ALLOCA_N(char,(unsigned int)(e+nf+2)); + str = rb_str_new(0, e+nf+2); + psz = RSTRING_PTR(str); n = (e+nf-1)/nf; pch = psz; @@ -591,10 +601,12 @@ BigDecimal_to_f(VALUE self) double d; S_LONG e; char *buf; + volatile VALUE str; GUARD_OBJ(p,GetVpValue(self,1)); if(VpVtoD(&d, &e, p)!=1) return rb_float_new(d); - buf = ALLOCA_N(char,(unsigned int)VpNumOfChars(p,"E")); + str = rb_str_new(0, VpNumOfChars(p,"E")); + buf = RSTRING_PTR(str); VpToString(p, buf, 0, 0); errno = 0; d = strtod(buf, 0); @@ -619,6 +631,8 @@ BigDecimal_to_r(VALUE self) VALUE a, digits, numerator; p = GetVpValue(self,1); + BigDecimal_check_num(p); + sign = VpGetSign(p); power = VpExponent10(p); a = BigDecimal_split(self); @@ -1155,7 +1169,10 @@ BigDecimal_div2(int argc, VALUE *argv, VALUE self) Real *mod; obj = BigDecimal_DoDivmod(self,b,&div,&mod); if(obj!=(VALUE)0) return obj; - return ToValue(div); + if(VpIsNaN(div) && rb_equal(b, INT2FIX(0))) { + rb_raise(rb_eZeroDivError, "divided by 0"); + } + return BigDecimal_to_i(ToValue(div)); } else { /* div in BigDecimal sense */ U_LONG ix = (U_LONG)GetPositiveInt(n); if(ix==0) return BigDecimal_div(self,b); @@ -1541,6 +1558,7 @@ BigDecimal_to_s(int argc, VALUE *argv, VALUE self) int fmt=0; /* 0:E format */ int fPlus=0; /* =0:default,=1: set ' ' before digits ,set '+' before digits. */ Real *vp; + volatile VALUE str; char *psz; char ch; U_LONG nc; @@ -1577,14 +1595,16 @@ BigDecimal_to_s(int argc, VALUE *argv, VALUE self) } if(mc>0) nc += (nc + mc - 1) / mc + 1; - psz = ALLOCA_N(char,(unsigned int)nc); + str = rb_str_new(0, nc); + psz = RSTRING_PTR(str); if(fmt) { VpToFString(vp, psz, mc, fPlus); } else { VpToString (vp, psz, mc, fPlus); } - return rb_str_new2(psz); + rb_str_resize(str, strlen(psz)); + return str; } /* Splits a BigDecimal number into four parts, returned as an array of values. @@ -1616,24 +1636,29 @@ BigDecimal_split(VALUE self) { ENTER(5); Real *vp; - VALUE obj,obj1; + VALUE obj,str; S_LONG e; S_LONG s; char *psz1; GUARD_OBJ(vp,GetVpValue(self,1)); - psz1 = ALLOCA_N(char,(unsigned int)VpNumOfChars(vp,"E")); + str = rb_str_new(0, VpNumOfChars(vp,"E")); + psz1 = RSTRING_PTR(str); VpSzMantissa(vp,psz1); s = 1; if(psz1[0]=='-') { - s = -1; ++psz1; + int len = strlen(psz1+1); + + memmove(psz1, psz1+1, len); + psz1[len] = '\0'; + s = -1; } if(psz1[0]=='N') s=0; /* NaN */ e = VpExponent10(vp); - obj1 = rb_str_new2(psz1); obj = rb_ary_new2(4); rb_ary_push(obj, INT2FIX(s)); - rb_ary_push(obj, obj1); + rb_ary_push(obj, str); + rb_str_resize(str, strlen(psz1)); rb_ary_push(obj, INT2FIX(10)); rb_ary_push(obj, INT2NUM(e)); return obj; @@ -1666,20 +1691,22 @@ BigDecimal_inspect(VALUE self) { ENTER(5); Real *vp; - VALUE obj; + volatile VALUE obj; unsigned int nc; - char *psz1; - char *pszAll; + char *psz, *tmp; GUARD_OBJ(vp,GetVpValue(self,1)); nc = VpNumOfChars(vp,"E"); nc +=(nc + 9) / 10; - psz1 = ALLOCA_N(char,nc); - pszAll = ALLOCA_N(char,nc+256); - VpToString(vp, psz1, 10, 0); - sprintf(pszAll,"#<BigDecimal:%lx,'%s',%lu(%lu)>",self,psz1,VpPrec(vp)*VpBaseFig(),VpMaxPrec(vp)*VpBaseFig()); - obj = rb_str_new2(pszAll); + obj = rb_str_new(0, nc+256); + psz = RSTRING_PTR(obj); + sprintf(psz,"#<BigDecimal:%lx,'",self); + tmp = psz + strlen(psz); + VpToString(vp, tmp, 10, 0); + tmp += strlen(tmp); + sprintf(tmp,"',%lu(%lu)>",VpPrec(vp)*VpBaseFig(),VpMaxPrec(vp)*VpBaseFig()); + rb_str_resize(obj, strlen(psz)); return obj; } @@ -2251,18 +2278,12 @@ VpException(unsigned short f, const char *str,int always) switch(f) { /* - case VP_EXCEPTION_ZERODIVIDE: case VP_EXCEPTION_OVERFLOW: */ + case VP_EXCEPTION_ZERODIVIDE: case VP_EXCEPTION_INFINITY: - exc = rb_eFloatDomainError; - goto raise; case VP_EXCEPTION_NaN: - exc = rb_eFloatDomainError; - goto raise; case VP_EXCEPTION_UNDERFLOW: - exc = rb_eFloatDomainError; - goto raise; case VP_EXCEPTION_OP: exc = rb_eFloatDomainError; goto raise; @@ -2534,6 +2555,7 @@ VpAlloc(U_LONG mx, const char *szVal) int sign=1; Real *vp = NULL; U_LONG mf = VpGetPrecLimit(); + volatile VALUE buf; mx = (mx + BASE_FIG - 1) / BASE_FIG + 1; /* Determine allocation unit. */ if(szVal) { @@ -2561,7 +2583,8 @@ VpAlloc(U_LONG mx, const char *szVal) /* Skip all '_' after digit: 2006-6-30 */ ni = 0; - psz = ALLOCA_N(char,strlen(szVal)+1); + buf = rb_str_new(0,strlen(szVal)+1); + psz = RSTRING_PTR(buf); i = 0; ipn = 0; while((psz[i]=szVal[ipn])!=0) { @@ -3656,7 +3679,7 @@ VPrint(FILE *fp, char *cntl_chr, Real *a) nc += fprintf(fp, "0."); n = a->Prec; for(i=0;i < n;++i) { - m = BASE1; + m = BASE1; e = a->frac[i]; while(m) { nn = e / m; @@ -3838,7 +3861,7 @@ VpToString(Real *a,char *psz,int fFmt,int fPlus) /* fPlus =0:default, =1: set ' ' before digits , =2:set '+' before digits. */ { U_LONG i, ZeroSup; - U_LONG n, m, e, nn; + U_LONG n, e; char *pszSav = psz; S_LONG ex; @@ -3854,18 +3877,12 @@ VpToString(Real *a,char *psz,int fFmt,int fPlus) *psz++ = '.'; n = a->Prec; for(i=0;i < n;++i) { - m = BASE1; e = a->frac[i]; - while(m) { - nn = e / m; - if((!ZeroSup) || nn) { - sprintf(psz, "%lu", nn); /* The reading zero(s) */ - psz += strlen(psz); - /* as 0.00xx will be ignored. */ - ZeroSup = 0; /* Set to print succeeding zeros */ - } - e = e - nn * m; - m /= 10; + if((!ZeroSup) || e) { + sprintf(psz, "%lu", e); /* The reading zero(s) */ + psz += strlen(psz); + /* as 0.00xx will be ignored. */ + ZeroSup = 0; /* Set to print succeeding zeros */ } } ex =(a->exponent) * BASE_FIG; diff --git a/ext/bigdecimal/bigdecimal.h b/ext/bigdecimal/bigdecimal.h index 3a300f1df5..a30a08e615 100644 --- a/ext/bigdecimal/bigdecimal.h +++ b/ext/bigdecimal/bigdecimal.h @@ -45,7 +45,7 @@ extern "C" { #define VP_EXCEPTION_NaN ((unsigned short)0x0002) #define VP_EXCEPTION_UNDERFLOW ((unsigned short)0x0004) #define VP_EXCEPTION_OVERFLOW ((unsigned short)0x0001) /* 0x0008) */ -#define VP_EXCEPTION_ZERODIVIDE ((unsigned short)0x0001) /* 0x0010) */ +#define VP_EXCEPTION_ZERODIVIDE ((unsigned short)0x0010) /* Following 2 exceptions cann't controlled by user */ #define VP_EXCEPTION_OP ((unsigned short)0x0020) diff --git a/ext/curses/curses.c b/ext/curses/curses.c index 778bee4da9..9f4e02ef42 100644 --- a/ext/curses/curses.c +++ b/ext/curses/curses.c @@ -573,6 +573,27 @@ curses_bkgd(VALUE obj, VALUE ch) } static VALUE +curses_escdelay_set(VALUE obj, VALUE val) +{ +#if defined(HAVE_ESCDELAY) + ESCDELAY=NUM2INT(val); + return INT2NUM(ESCDELAY); +#else + rb_notimplement(); +#endif +} + +static VALUE +curses_escdelay_get(VALUE obj) +{ +#if defined(HAVE_ESCDELAY) + return INT2NUM(ESCDELAY); +#else + rb_notimplement(); +#endif +} + +static VALUE curses_resizeterm(VALUE obj, VALUE lin, VALUE col) { #if defined(HAVE_RESIZETERM) @@ -1419,6 +1440,8 @@ Init_curses(void) rb_define_method(cMouseEvent, "bstate", curs_mouse_bstate, 0); #endif /* USE_MOUSE */ + rb_define_module_function(mCurses, "ESCDELAY=", curses_escdelay_set, 1); + rb_define_module_function(mCurses, "ESCDELAY", curses_escdelay_get, 0); rb_define_module_function(mCurses, "init_screen", curses_init_screen, 0); rb_define_module_function(mCurses, "close_screen", curses_close_screen, 0); rb_define_module_function(mCurses, "closed?", curses_closed, 0); diff --git a/ext/curses/extconf.rb b/ext/curses/extconf.rb index 799d1bfe5f..3aa91702e3 100644 --- a/ext/curses/extconf.rb +++ b/ext/curses/extconf.rb @@ -6,6 +6,7 @@ dir_config('termcap') make=false headers = [] + have_library("mytinfo", "tgetent") if /bow/ =~ RUBY_PLATFORM have_library("tinfo", "tgetent") or have_library("termcap", "tgetent") if have_header(*curses=%w"ncurses.h") and have_library("ncurses", "initscr") @@ -27,5 +28,6 @@ if make if try_static_assert("sizeof(char*)>sizeof(int)", %w[stdio.h stdlib.h]+curses , flag) $defs << flag end + have_var("ESCDELAY", curses) create_makefile("curses") end diff --git a/ext/gdbm/gdbm.c b/ext/gdbm/gdbm.c index 1e83608132..edde0d19ab 100644 --- a/ext/gdbm/gdbm.c +++ b/ext/gdbm/gdbm.c @@ -344,6 +344,7 @@ rb_gdbm_nextkey(GDBM_FILE dbm, VALUE keystr) return Qnil; str = rb_str_new(key2.dptr, key2.dsize); + free(key2.dptr); OBJ_TAINT(str); return str; } diff --git a/ext/pty/pty.c b/ext/pty/pty.c index e0d571a581..f0b8e66595 100644 --- a/ext/pty/pty.c +++ b/ext/pty/pty.c @@ -127,51 +127,8 @@ echild_status(VALUE self) struct pty_info { int fd; rb_pid_t child_pid; - VALUE thread; }; -static void -raise_from_wait(const char *state, const struct pty_info *info) -{ - char buf[1024]; - VALUE exc; - - snprintf(buf, sizeof(buf), "pty - %s: %ld", state, (long)info->child_pid); - exc = rb_exc_new2(eChildExited, buf); - rb_iv_set(exc, "status", rb_last_status_get()); - rb_funcall(info->thread, rb_intern("raise"), 1, exc); -} - -static VALUE -pty_syswait(void *arg) -{ - const struct pty_info *const info = arg; - rb_pid_t cpid; - int status; - - for (;;) { - cpid = rb_waitpid(info->child_pid, &status, WUNTRACED); - if (cpid == -1) return Qnil; - -#if defined(WIFSTOPPED) -#elif defined(IF_STOPPED) -#define WIFSTOPPED(status) IF_STOPPED(status) -#else ----->> Either IF_STOPPED or WIFSTOPPED is needed <<---- -#endif /* WIFSTOPPED | IF_STOPPED */ - if (WIFSTOPPED(status)) { /* suspend */ - raise_from_wait("stopped", info); - } - else if (kill(info->child_pid, 0) == 0) { - raise_from_wait("changed", info); - } - else { - raise_from_wait("exited", info); - return Qnil; - } - } -} - static void getDevice(int*, int*, char [DEVICELEN]); struct exec_info { @@ -217,7 +174,6 @@ establishShell(int argc, VALUE *argv, struct pty_info *info, } getDevice(&master, &slave, SlaveName); - info->thread = rb_thread_current(); if ((pid = fork()) < 0) { close(master); close(slave); @@ -288,15 +244,6 @@ establishShell(int argc, VALUE *argv, struct pty_info *info, info->fd = master; } -static VALUE -pty_finalize_syswait(struct pty_info *info) -{ - rb_thread_kill(info->thread); - rb_funcall(info->thread, rb_intern("value"), 0); - rb_detach_process(info->child_pid); - return Qnil; -} - static int get_device_once(int *master, int *slave, char SlaveName[DEVICELEN], int fail) { @@ -396,13 +343,19 @@ getDevice(int *master, int *slave, char SlaveName[DEVICELEN]) } } +static VALUE +pty_detach_process(struct pty_info *info) +{ + rb_detach_process(info->child_pid); + return Qnil; +} + /* ruby function: getpty */ static VALUE pty_getpty(int argc, VALUE *argv, VALUE self) { VALUE res; struct pty_info info; - struct pty_info thinfo; rb_io_t *wfptr,*rfptr; VALUE rport = rb_obj_alloc(rb_cFile); VALUE wport = rb_obj_alloc(rb_cFile); @@ -426,32 +379,55 @@ pty_getpty(int argc, VALUE *argv, VALUE self) rb_ary_store(res,1,(VALUE)wport); rb_ary_store(res,2,PIDT2NUM(info.child_pid)); - thinfo.thread = rb_thread_create(pty_syswait, (void*)&info); - thinfo.child_pid = info.child_pid; - rb_thread_schedule(); - if (rb_block_given_p()) { - rb_ensure(rb_yield, res, pty_finalize_syswait, (VALUE)&thinfo); + rb_ensure(rb_yield, res, pty_detach_process, (VALUE)&info); return Qnil; } return res; } -/* ruby function: protect_signal - obsolete */ -static VALUE -pty_protect(VALUE self) +static void +raise_from_check(pid_t pid, int status) { - rb_warn("PTY::protect_signal is no longer needed"); - rb_yield(Qnil); - return self; + const char *state; + char buf[1024]; + VALUE exc; + +#if defined(WIFSTOPPED) +#elif defined(IF_STOPPED) +#define WIFSTOPPED(status) IF_STOPPED(status) +#else +---->> Either IF_STOPPED or WIFSTOPPED is needed <<---- +#endif /* WIFSTOPPED | IF_STOPPED */ + if (WIFSTOPPED(status)) { /* suspend */ + state = "stopped"; + } + else if (kill(pid, 0) == 0) { + state = "changed"; + } + else { + state = "exited"; + } + snprintf(buf, sizeof(buf), "pty - %s: %ld", state, (long)pid); + exc = rb_exc_new2(eChildExited, buf); + rb_iv_set(exc, "status", rb_last_status_get()); + rb_exc_raise(exc); } -/* ruby function: reset_signal - obsolete */ static VALUE -pty_reset_signal(VALUE self) +pty_check(int argc, VALUE *argv, VALUE self) { - rb_warn("PTY::reset_signal is no longer needed"); - return self; + VALUE pid, exc; + pid_t cpid; + int status; + + rb_scan_args(argc, argv, "11", &pid, &exc); + cpid = rb_waitpid(NUM2PIDT(pid), &status, WUNTRACED); + if (cpid == -1) return Qnil; + + if (!RTEST(exc)) return status; + raise_from_check(pid, status); + return Qnil; /* not reached */ } static VALUE cPTY; @@ -462,8 +438,7 @@ Init_pty() cPTY = rb_define_module("PTY"); rb_define_module_function(cPTY,"getpty",pty_getpty,-1); rb_define_module_function(cPTY,"spawn",pty_getpty,-1); - rb_define_module_function(cPTY,"protect_signal",pty_protect,0); - rb_define_module_function(cPTY,"reset_signal",pty_reset_signal,0); + rb_define_singleton_function(cPTY,"check",pty_check,-1); eChildExited = rb_define_class_under(cPTY,"ChildExited",rb_eRuntimeError); rb_define_method(eChildExited,"status",echild_status,0); diff --git a/ext/syck/rubyext.c b/ext/syck/rubyext.c index d5c6372076..a8f0eec978 100644 --- a/ext/syck/rubyext.c +++ b/ext/syck/rubyext.c @@ -50,11 +50,11 @@ typedef struct { * symbols and constants */ static ID s_new, s_utc, s_at, s_to_f, s_to_i, s_read, s_binmode, s_call, s_cmp, s_transfer, s_update, s_dup, s_haskey, s_match, s_keys, s_unpack, s_tr_bang, s_default_set, s_tag_read_class, s_tag_subclasses, s_resolver, s_push, s_emitter, s_level, s_detect_implicit, s_node_import, s_out, s_input, s_intern, s_transform, s_yaml_new, s_yaml_initialize, s_node_export, s_to_yaml, s_write, s_set_resolver, s_each; -static ID s_tags, s_kind, s_name, s_options, s_type_id, s_type_id_set, s_style, s_style_set, s_value, s_value_set; +static ID s_tags, s_kind, s_name, s_options, s_type_id, s_type_id_set, s_style, s_style_set, s_value, s_value_set, s_parse; static VALUE sym_model, sym_generic, sym_input, sym_bytecode; static VALUE sym_scalar, sym_seq, sym_map; static VALUE sym_1quote, sym_2quote, sym_fold, sym_literal, sym_plain, sym_inline; -static VALUE cDate, cNode, cMap, cSeq, cScalar, cOut, cParser, cResolver, cPrivateType, cDomainType, cYObject, cBadAlias, cDefaultKey, cMergeKey, cEmitter; +static VALUE cDate, cNode, cMap, cSeq, cScalar, cOut, cParser, cResolver, cPrivateType, cDomainType, cYObject, cBadAlias, cDefaultKey, cMergeKey, cEmitter, cDateTime; static VALUE oDefaultResolver, oGenericResolver; /* @@ -207,10 +207,17 @@ syck_get_hash_aref(VALUE hsh, VALUE key) /* * creating timestamps */ +struct mktime_arg { + char *str; + long len; +}; + SYMID -rb_syck_mktime(char *str, long len) +mktime_do(struct mktime_arg *arg) { VALUE time; + char *str = arg->str; + long len = arg->len; char *ptr = str; VALUE year = INT2FIX(0); VALUE mon = INT2FIX(0); @@ -312,6 +319,29 @@ rb_syck_mktime(char *str, long len) } } +SYMID +mktime_r(struct mktime_arg *arg) +{ + if (!cDateTime) { + /* + * Load Date module + */ + rb_require("date"); + cDateTime = rb_const_get(rb_cObject, rb_intern("DateTime")); + } + return rb_funcall(cDateTime, s_parse, 1, rb_str_new(arg->str, arg->len)); +} + +SYMID +rb_syck_mktime(char *str, long len) +{ + struct mktime_arg a; + + a.str = str; + a.len = len; + return rb_rescue2(mktime_do, (VALUE)&a, mktime_r, (VALUE)&a, rb_eArgError, NULL); +} + /* * handles merging of an array of hashes * (see http://www.yaml.org/type/merge/) @@ -2112,6 +2142,7 @@ Init_syck() s_yaml_new = rb_intern("yaml_new"); s_yaml_initialize = rb_intern("yaml_initialize"); s_each = rb_intern("each"); + s_parse = rb_intern("parse"); s_tags = rb_intern("@tags"); s_name = rb_intern("@name"); diff --git a/ext/tk/ChangeLog.tkextlib b/ext/tk/ChangeLog.tkextlib index 8c5d01a954..fc919a5eb5 100644 --- a/ext/tk/ChangeLog.tkextlib +++ b/ext/tk/ChangeLog.tkextlib @@ -1,3 +1,14 @@ +Tue Nov 25 03:37:42 2008 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp> + + * ext/tk/lib/tkextlib/blt/tabset.rb, + ext/tk/lib/tkextlib/blt/tabnotebook.rb: + fix many bugs. Now, those work properly. + +Sat Nov 22 10:31:25 2008 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp> + + * ext/tk/lib/tkextlib/blt.rb, ext/tk/lib/tkextlib/blt/vector.rb: + fix NameError bug. + 2008-05-12 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp> * ext/tk/lib/tkextlib/tkDND/shape.rb: wrong package name. diff --git a/ext/tk/lib/tkextlib/blt.rb b/ext/tk/lib/tkextlib/blt.rb index 115eb927ba..8d58c1f1bc 100644 --- a/ext/tk/lib/tkextlib/blt.rb +++ b/ext/tk/lib/tkextlib/blt.rb @@ -26,14 +26,14 @@ module Tk PATCH_LEVEL = tk_call('set', 'blt_patchLevel') begin - lib = INTERP._invoke('set', 'blt_library') + lib = TkCore::INTERP._invoke('set', 'blt_library') rescue lib = '' end LIBRARY = TkVarAccess.new('blt_library', lib) begin - lib = INTERP._invoke('set', 'blt_libPath') + lib = TkCore::INTERP._invoke('set', 'blt_libPath') rescue lib = '' end diff --git a/ext/tk/lib/tkextlib/blt/tabnotebook.rb b/ext/tk/lib/tkextlib/blt/tabnotebook.rb index 508fa2b82f..510352ba48 100644 --- a/ext/tk/lib/tkextlib/blt/tabnotebook.rb +++ b/ext/tk/lib/tkextlib/blt/tabnotebook.rb @@ -13,9 +13,98 @@ module Tk::BLT WidgetClassName = 'Tabnotebook'.freeze WidgetClassNames[WidgetClassName] = self + class Tab < Tk::BLT::Tabset::Tab + def self.new(parent, pos=nil, name=nil, keys={}) + if pos.kind_of?(Hash) + keys = pos + name = nil + pos = nil + end + if name.kind_of?(Hash) + keys = name + name = nil + end + obj = nil + TabID_TBL.mutex.synchronize{ + if name && TabID_TBL[parent.path] && TabID_TBL[parent.path][name] + obj = TabID_TBL[parent.path][name] + if pos + if pos.to_s == 'end' + obj.move_after('end') + else + obj.move_before(pos) + end + end + obj.configure if keys && ! keys.empty? + else + (obj = self.allocate).instance_eval{ + initialize(parent, pos, name, keys) + TabID_TBL[@tpath] = {} unless TabID_TBL[@tpath] + TabID_TBL[@tpath][@id] = self + } + end + } + obj + end + + def initialize(parent, pos, name, keys) + @t = parent + @tpath = parent.path + if name + @path = @id = name + unless (list(tk_call(@tpath, 'tab', 'names', @id)).empty?) + if pos + idx = tk_call(@tpath, 'index', @id) + if pos.to_s == 'end' + tk_call(@tpath, 'move', idx, 'after', 'end') + else + tk_call(@tpath, 'move', idx, 'before', pos) + end + end + tk_call(@tpath, 'tab', 'configure', @id, keys) + else + fail ArgumentError, "can't find tab \"#{@id}\" in #{@t}" + end + else + pos = 'end' unless pos + @path = @id = tk_call(@tpath, 'insert', pos, keys) + end + end + end + + ####################################### + def get_tab(index) - Tk::BLT::Tabset::Tab.id2obj(tk_send_without_enc('id', tagindex(index))) + if (idx = tk_send_without_enc('id', tagindex(index))).empty? + nil + else + Tk::BLT::Tabset::Tab.id2obj(self, idx) + end end alias get_id get_tab + + def get_tabobj(index) + if (idx = tk_send_without_enc('id', tagindex(index))).empty? + nil + else + Tk::BLT::Tabnotebook::Tab.new(self, nil, idx) + end + end + + alias index_name index + + def insert(pos=nil, keys={}) + if pos.kind_of?(Hash) + keys = pos + pos = nil + end + pos = 'end' if pos.nil? + Tk::BLT::Tabnotebook::Tab.new(self, nil, + tk_send('insert', tagindex(pos), keys)) + + end + undef :insert_tabs + + undef :tab_pageheight, :tab_pagewidth end end diff --git a/ext/tk/lib/tkextlib/blt/tabset.rb b/ext/tk/lib/tkextlib/blt/tabset.rb index ca81ad8f95..b5e076db3a 100644 --- a/ext/tk/lib/tkextlib/blt/tabset.rb +++ b/ext/tk/lib/tkextlib/blt/tabset.rb @@ -27,7 +27,7 @@ module Tk::BLT tpath = tabset.path TabID_TBL.mutex.synchronize{ if TabID_TBL[tpath] - TabID_TBL[tpath][id]? TabID_TBL[tpath]: id + TabID_TBL[tpath][id]? TabID_TBL[tpath][id]: id else id end @@ -48,6 +48,13 @@ module Tk::BLT TabID_TBL.mutex.synchronize{ if name && TabID_TBL[parent.path] && TabID_TBL[parent.path][name] obj = TabID_TBL[parent.path][name] + if pos + if pos.to_s == 'end' + obj.move_after('end') + else + obj.move_before(pos) + end + end obj.configure if keys && ! keys.empty? else (obj = self.allocate).instance_eval{ @@ -69,9 +76,9 @@ module Tk::BLT if pos idx = tk_call(@tpath, 'index', '-name', @id) if pos.to_s == 'end' - tk_call(@tpath, idx, 'moveto', 'after', 'end') + tk_call(@tpath, 'move', idx, 'after', 'end') else - tk_call(@tpath, idx, 'moveto', 'before', pos) + tk_call(@tpath, 'move', idx, 'before', pos) end end tk_call(@tpath, 'tab', 'configure', @id, keys) @@ -80,11 +87,11 @@ module Tk::BLT tk_call(@tpath, 'insert', pos, @id, keys) end else + pos = 'end' unless pos TabsetTab_ID.mutex.synchronize{ @path = @id = TabsetTab_ID.join(TkCore::INTERP._ip_id_) TabsetTab_ID[1].succ! } - pos = 'end' unless pos tk_call(@tpath, 'insert', pos, @id, keys) end end @@ -173,10 +180,10 @@ module Tk::BLT end def perforation_highlight(mode) - @t.perforation.highlight(self.index, mode) + @t.perforation_highlight(self.index, mode) end def perforation_invoke() - @t.perforation.invoke(self.index) + @t.perforation_invoke(self.index) end def see() @@ -335,19 +342,43 @@ module Tk::BLT end def get_tab(index) - Tk::BLT::Tabset::Tab.id2obj(tk_send_without_enc('get', tagindex(index))) + if (idx = tk_send_without_enc('get', tagindex(index))).empty? + nil + else + Tk::BLT::Tabset::Tab.id2obj(self, idx) + end + end + def get_tabobj(index) + if (idx = tk_send_without_enc('get', tagindex(index))).empty? + nil + else + Tk::BLT::Tabset::Tab.new(self, nil, name, {}) + end end def index(str) num_or_str(tk_send('index', str)) end def index_name(tab) - num_or_str(tk_send('index', '-mame', tagid(tab))) + num_or_str(tk_send('index', '-name', tagid(tab))) end def insert(pos, tab, keys={}) + pos = 'end' if pos.nil? Tk::BLT::Tabset::Tab.new(self, tagindex(pos), tagid(tab), keys) end + def insert_tabs(pos, *tabs) + pos = 'end' if pos.nil? + if tabs[-1].kind_of?(Hash) + keys = tabs.pop + else + keys = {} + end + fail ArgumentError, 'no tabs is given' if tabs.empty? + tabs.map!{|tab| tagid(tab)} + tk_send('insert', tagindex(pos), *(tabs + [keys])) + tabs.collect{|tab| Tk::BLT::Tabset::Tab.new(self, nil, tagid(tab))} + end def invoke(index) tk_send('invoke', tagindex(index)) @@ -363,15 +394,31 @@ module Tk::BLT end def nearest(x, y) - Tk::BLT::Tabset::Tab.id2obj(num_or_str(tk_send_without_enc('nearest', x, y))) + Tk::BLT::Tabset::Tab.id2obj(self, num_or_str(tk_send_without_enc('nearest', x, y))) end - def perforation_highlight(index, mode) - tk_send('perforation', 'highlight', tagindex(index), mode) + def perforation_activate(mode) + tk_send('perforation', 'activate', mode) self end - def perforation_invoke(index) - tk_send('perforation', 'invoke', tagindex(index)) + def perforation_highlight(index, *args) + if args.empty? + # index --> mode + tk_send('perforation', 'highlight', index) + elsif args.size == 1 + # args[0] --> mode + tk_send('perforation', 'highlight', tagindex(index), args[0]) + else # Error: call to get Tcl's error message + tk_send('perforation', 'highlight', tagindex(index), *args) + end + self + end + def perforation_invoke(index=nil) + if index + tk_send('perforation', 'invoke', tagindex(index)) + else + tk_send('perforation', 'invoke') + end end def scan_mark(x, y) @@ -397,14 +444,37 @@ module Tk::BLT self end + def tab_dockall + tk_send('tab', 'dockall') + self + end + def tab_names(pat=None) simplelist(tk_send('tab', 'names', pat)).collect{|name| - Tk::BLT::Tabset::Tab.id2obj(name) + Tk::BLT::Tabset::Tab.id2obj(self, name) + } + end + + def tab_objs(pat=None) + simplelist(tk_send('tab', 'names', pat)).collect{|name| + Tk::BLT::Tabset::Tab.new(self, nil, name, {}) } end - def tab_tearoff(index, name=None) - window(tk_send('tab', 'tearoff', tagindex(index), name)) + def tab_ids(pat=None) + simplelist(tk_send('tab', 'names', pat)) + end + + def tab_pageheight + number(tk_send('tab', 'pageheight')) + end + + def tab_pagewidth + number(tk_send('tab', 'pagewidth')) + end + + def tab_tearoff(index, parent=None) + window(tk_send('tab', 'tearoff', tagindex(index), parent)) end def xscrollcommand(cmd=Proc.new) diff --git a/ext/tk/lib/tkextlib/blt/vector.rb b/ext/tk/lib/tkextlib/blt/vector.rb index 76c12a24e8..97fb1b96ff 100644 --- a/ext/tk/lib/tkextlib/blt/vector.rb +++ b/ext/tk/lib/tkextlib/blt/vector.rb @@ -49,11 +49,11 @@ module Tk::BLT size = size.join(':') end if size - @id = INTERP._invoke('::blt::vector', 'create', - "#auto(#{size})", *hash_kv(keys)) + @id = TkCore::INTERP._invoke('::blt::vector', 'create', + "#auto(#{size})", *hash_kv(keys)) else - @id = INTERP._invoke('::blt::vector', 'create', - "#auto", *hash_kv(keys)) + @id = TkCore::INTERP._invoke('::blt::vector', 'create', + "#auto", *hash_kv(keys)) end TkVar_ID_TBL.mutex.synchronize{ @@ -68,7 +68,7 @@ module Tk::BLT @trace_opts = nil # teach Tk-ip that @id is global var - INTERP._invoke_without_enc('global', @id) + TkCore::INTERP._invoke_without_enc('global', @id) end def destroy @@ -250,7 +250,7 @@ module Tk::BLT @trace_opts = nil # teach Tk-ip that @id is global var - INTERP._invoke_without_enc('global', @id) + TkCore::INTERP._invoke_without_enc('global', @id) end end end diff --git a/ext/tk/lib/tkextlib/version.rb b/ext/tk/lib/tkextlib/version.rb index 434ed11a2e..82ed7ef542 100644 --- a/ext/tk/lib/tkextlib/version.rb +++ b/ext/tk/lib/tkextlib/version.rb @@ -2,5 +2,5 @@ # release date of tkextlib # module Tk - Tkextlib_RELEASE_DATE = '2008-05-23'.freeze + Tkextlib_RELEASE_DATE = '2008-11-25'.freeze end @@ -1298,7 +1298,7 @@ rb_file_world_writable_p(VALUE obj, VALUE fname) #ifdef S_IWOTH struct stat st; - if (rb_stat(fname, &st) < 0) return Qfalse; + if (rb_stat(fname, &st) < 0) return Qnil; if ((st.st_mode & (S_IWOTH)) == S_IWOTH) { return UINT2NUM(st.st_mode & (S_IRUGO|S_IWUGO|S_IXUGO)); } diff --git a/lib/date.rb b/lib/date.rb index 3da3d21f8b..2c9792562b 100644 --- a/lib/date.rb +++ b/lib/date.rb @@ -1470,7 +1470,9 @@ class Date def hash() @ajd.hash end # Return internal object state as a programmer-readable string. - def inspect() format('#<%s: %s,%s,%s>', self.class, @ajd, @of, @sg) end + def inspect + format('#<%s: %s (%s,%s,%s)>', self.class, to_s, @ajd, @of, @sg) + end # Return the date as a human-readable string. # diff --git a/lib/date/format.rb b/lib/date/format.rb index c8bc10fbac..161cf85891 100644 --- a/lib/date/format.rb +++ b/lib/date/format.rb @@ -255,6 +255,7 @@ class Date when 'j'; emit_n(yday, 3, f) when 'k'; emit_a(hour, 2, f) when 'L' + f[:p] = nil w = f[:w] || 3 u = 10**w emit_n((sec_fraction * u).floor, w, f) @@ -262,6 +263,7 @@ class Date when 'M', 'OM'; emit_n(min, 2, f) when 'm', 'Om'; emit_n(mon, 2, f) when 'N' + f[:p] = nil w = f[:w] || 9 u = 10**w emit_n((sec_fraction * u).floor, w, f) diff --git a/lib/logger.rb b/lib/logger.rb index 26d7d9d560..07699e7017 100644 --- a/lib/logger.rb +++ b/lib/logger.rb @@ -182,7 +182,13 @@ require 'monitor' class Logger VERSION = "1.2.6" id, name, rev = %w$Id$ - ProgName = "#{name.chomp(",v")}/#{rev}" + if name + name = name.chomp(",v") + else + name = File.basename(__FILE__) + end + rev ||= "v#{VERSION}" + ProgName = "#{name}/#{rev}" class Error < RuntimeError; end class ShiftingError < Error; end diff --git a/lib/minitest/unit.rb b/lib/minitest/unit.rb index 460258cdf2..df6394a8eb 100644 --- a/lib/minitest/unit.rb +++ b/lib/minitest/unit.rb @@ -191,12 +191,12 @@ module MiniTest assert caught, message(msg) { default } end - def capture_io - require 'stringio' + def capture_io + require 'stringio' - orig_stdout, orig_stderr = $stdout, $stderr - captured_stdout, captured_stderr = StringIO.new, StringIO.new - $stdout, $stderr = captured_stdout, captured_stderr + orig_stdout, orig_stderr = $stdout, $stderr + captured_stdout, captured_stderr = StringIO.new, StringIO.new + $stdout, $stderr = captured_stdout, captured_stderr yield diff --git a/lib/time.rb b/lib/time.rb index 2d0a96117d..3555571f22 100644 --- a/lib/time.rb +++ b/lib/time.rb @@ -84,9 +84,27 @@ class Time end def zone_utc?(zone) - # * -0000 means localtime. [RFC 2822] - # * GMT is a localtime abbreviation in Europe/London, etc. - if /\A(?:\+00:00|\+0000|\+00|UTC|Z|UT)\z/i =~ zone + # * +0000 + # In RFC 2822, +0000 indicate a time zone at Universal Time. + # Europe/London is "a time zone at Universal Time" in Winter. + # Europe/Lisbon is "a time zone at Universal Time" in Winter. + # Atlantic/Reykjavik is "a time zone at Universal Time". + # Africa/Dakar is "a time zone at Universal Time". + # So +0000 is a local time such as Europe/London, etc. + # * GMT + # GMT is used as a time zone abbreviation in Europe/London, + # Africa/Dakar, etc. + # So it is a local time. + # + # * -0000, -00:00 + # In RFC 2822, -0000 the date-time contains no information about the + # local time zone. + # In RFC 3339, -00:00 is used for the time in UTC is known, + # but the offset to local time is unknown. + # They are not appropriate for specific time zone such as + # Europe/London because time zone neutral, + # So -00:00 and -0000 are treated as UTC. + if /\A(?:-00:00|-0000|-00|UTC|Z|UT)\z/i =~ zone true else false @@ -409,7 +427,7 @@ class Time # # where zone is [+-]hhmm. # - # If +self+ is a UTC time, +0000 is used as zone. + # If +self+ is a UTC time, -0000 is used as zone. # def rfc2822 sprintf('%s, %02d %s %d %02d:%02d:%02d ', @@ -417,7 +435,7 @@ class Time day, RFC2822_MONTH_NAME[mon-1], year, hour, min, sec) + if utc? - '+0000' + '-0000' else off = utc_offset sign = off < 0 ? '-' : '+' @@ -730,86 +748,98 @@ if __FILE__ == $0 def test_zone_0000 assert_equal(true, Time.parse("2000-01-01T00:00:00Z").utc?) - assert_equal(true, Time.parse("2000-01-01T00:00:00+00:00").utc?) - assert_equal(false, Time.parse("2000-01-01T00:00:00-00:00").utc?) + assert_equal(true, Time.parse("2000-01-01T00:00:00-00:00").utc?) + assert_equal(false, Time.parse("2000-01-01T00:00:00+00:00").utc?) assert_equal(false, Time.parse("Sat, 01 Jan 2000 00:00:00 GMT").utc?) - assert_equal(true, Time.parse("Sat, 01 Jan 2000 00:00:00 +0000").utc?) - assert_equal(false, Time.parse("Sat, 01 Jan 2000 00:00:00 -0000").utc?) + assert_equal(true, Time.parse("Sat, 01 Jan 2000 00:00:00 -0000").utc?) + assert_equal(false, Time.parse("Sat, 01 Jan 2000 00:00:00 +0000").utc?) assert_equal(false, Time.rfc2822("Sat, 01 Jan 2000 00:00:00 GMT").utc?) - assert_equal(true, Time.rfc2822("Sat, 01 Jan 2000 00:00:00 +0000").utc?) - assert_equal(false, Time.rfc2822("Sat, 01 Jan 2000 00:00:00 -0000").utc?) + assert_equal(true, Time.rfc2822("Sat, 01 Jan 2000 00:00:00 -0000").utc?) + assert_equal(false, Time.rfc2822("Sat, 01 Jan 2000 00:00:00 +0000").utc?) assert_equal(true, Time.rfc2822("Sat, 01 Jan 2000 00:00:00 UTC").utc?) end + def test_rfc2822_utc_roundtrip_winter + t1 = Time.local(2008,12,1) + t2 = Time.rfc2822(t1.rfc2822) + assert_equal(t1.utc?, t2.utc?, "[ruby-dev:37126]") + end + + def test_rfc2822_utc_roundtrip_summer + t1 = Time.local(2008,8,1) + t2 = Time.rfc2822(t1.rfc2822) + assert_equal(t1.utc?, t2.utc?) + end + def test_parse_leap_second t = Time.utc(1998,12,31,23,59,59) assert_equal(t, Time.parse("Thu Dec 31 23:59:59 UTC 1998")) - assert_equal(t, Time.parse("Fri Dec 31 23:59:59 +0000 1998"));t.localtime + assert_equal(t, Time.parse("Fri Dec 31 23:59:59 -0000 1998"));t.localtime assert_equal(t, Time.parse("Fri Jan 1 08:59:59 +0900 1999")) assert_equal(t, Time.parse("Fri Jan 1 00:59:59 +0100 1999")) - assert_equal(t, Time.parse("Fri Dec 31 23:59:59 -0000 1998")) + assert_equal(t, Time.parse("Fri Dec 31 23:59:59 +0000 1998")) assert_equal(t, Time.parse("Fri Dec 31 22:59:59 -0100 1998"));t.utc t += 1 assert_equal(t, Time.parse("Thu Dec 31 23:59:60 UTC 1998")) - assert_equal(t, Time.parse("Fri Dec 31 23:59:60 +0000 1998"));t.localtime + assert_equal(t, Time.parse("Fri Dec 31 23:59:60 -0000 1998"));t.localtime assert_equal(t, Time.parse("Fri Jan 1 08:59:60 +0900 1999")) assert_equal(t, Time.parse("Fri Jan 1 00:59:60 +0100 1999")) - assert_equal(t, Time.parse("Fri Dec 31 23:59:60 -0000 1998")) + assert_equal(t, Time.parse("Fri Dec 31 23:59:60 +0000 1998")) assert_equal(t, Time.parse("Fri Dec 31 22:59:60 -0100 1998"));t.utc t += 1 if t.sec == 60 assert_equal(t, Time.parse("Thu Jan 1 00:00:00 UTC 1999")) - assert_equal(t, Time.parse("Fri Jan 1 00:00:00 +0000 1999"));t.localtime + assert_equal(t, Time.parse("Fri Jan 1 00:00:00 -0000 1999"));t.localtime assert_equal(t, Time.parse("Fri Jan 1 09:00:00 +0900 1999")) assert_equal(t, Time.parse("Fri Jan 1 01:00:00 +0100 1999")) - assert_equal(t, Time.parse("Fri Jan 1 00:00:00 -0000 1999")) + assert_equal(t, Time.parse("Fri Jan 1 00:00:00 +0000 1999")) assert_equal(t, Time.parse("Fri Dec 31 23:00:00 -0100 1998")) end def test_rfc2822_leap_second t = Time.utc(1998,12,31,23,59,59) assert_equal(t, Time.rfc2822("Thu, 31 Dec 1998 23:59:59 UTC")) - assert_equal(t, Time.rfc2822("Fri, 31 Dec 1998 23:59:59 +0000"));t.localtime + assert_equal(t, Time.rfc2822("Fri, 31 Dec 1998 23:59:59 -0000"));t.localtime assert_equal(t, Time.rfc2822("Fri, 1 Jan 1999 08:59:59 +0900")) assert_equal(t, Time.rfc2822("Fri, 1 Jan 1999 00:59:59 +0100")) - assert_equal(t, Time.rfc2822("Fri, 31 Dec 1998 23:59:59 -0000")) + assert_equal(t, Time.rfc2822("Fri, 31 Dec 1998 23:59:59 +0000")) assert_equal(t, Time.rfc2822("Fri, 31 Dec 1998 22:59:59 -0100"));t.utc t += 1 assert_equal(t, Time.rfc2822("Thu, 31 Dec 1998 23:59:60 UTC")) - assert_equal(t, Time.rfc2822("Fri, 31 Dec 1998 23:59:60 +0000"));t.localtime + assert_equal(t, Time.rfc2822("Fri, 31 Dec 1998 23:59:60 -0000"));t.localtime assert_equal(t, Time.rfc2822("Fri, 1 Jan 1999 08:59:60 +0900")) assert_equal(t, Time.rfc2822("Fri, 1 Jan 1999 00:59:60 +0100")) - assert_equal(t, Time.rfc2822("Fri, 31 Dec 1998 23:59:60 -0000")) + assert_equal(t, Time.rfc2822("Fri, 31 Dec 1998 23:59:60 +0000")) assert_equal(t, Time.rfc2822("Fri, 31 Dec 1998 22:59:60 -0100"));t.utc t += 1 if t.sec == 60 assert_equal(t, Time.rfc2822("Thu, 1 Jan 1999 00:00:00 UTC")) - assert_equal(t, Time.rfc2822("Fri, 1 Jan 1999 00:00:00 +0000"));t.localtime + assert_equal(t, Time.rfc2822("Fri, 1 Jan 1999 00:00:00 -0000"));t.localtime assert_equal(t, Time.rfc2822("Fri, 1 Jan 1999 09:00:00 +0900")) assert_equal(t, Time.rfc2822("Fri, 1 Jan 1999 01:00:00 +0100")) - assert_equal(t, Time.rfc2822("Fri, 1 Jan 1999 00:00:00 -0000")) + assert_equal(t, Time.rfc2822("Fri, 1 Jan 1999 00:00:00 +0000")) assert_equal(t, Time.rfc2822("Fri, 31 Dec 1998 23:00:00 -0100")) end def test_xmlschema_leap_second t = Time.utc(1998,12,31,23,59,59) assert_equal(t, Time.xmlschema("1998-12-31T23:59:59Z")) - assert_equal(t, Time.xmlschema("1998-12-31T23:59:59+00:00"));t.localtime + assert_equal(t, Time.xmlschema("1998-12-31T23:59:59-00:00"));t.localtime assert_equal(t, Time.xmlschema("1999-01-01T08:59:59+09:00")) assert_equal(t, Time.xmlschema("1999-01-01T00:59:59+01:00")) - assert_equal(t, Time.xmlschema("1998-12-31T23:59:59-00:00")) + assert_equal(t, Time.xmlschema("1998-12-31T23:59:59+00:00")) assert_equal(t, Time.xmlschema("1998-12-31T22:59:59-01:00"));t.utc t += 1 assert_equal(t, Time.xmlschema("1998-12-31T23:59:60Z")) - assert_equal(t, Time.xmlschema("1998-12-31T23:59:60+00:00"));t.localtime + assert_equal(t, Time.xmlschema("1998-12-31T23:59:60-00:00"));t.localtime assert_equal(t, Time.xmlschema("1999-01-01T08:59:60+09:00")) assert_equal(t, Time.xmlschema("1999-01-01T00:59:60+01:00")) - assert_equal(t, Time.xmlschema("1998-12-31T23:59:60-00:00")) + assert_equal(t, Time.xmlschema("1998-12-31T23:59:60+00:00")) assert_equal(t, Time.xmlschema("1998-12-31T22:59:60-01:00"));t.utc t += 1 if t.sec == 60 assert_equal(t, Time.xmlschema("1999-01-01T00:00:00Z")) - assert_equal(t, Time.xmlschema("1999-01-01T00:00:00+00:00"));t.localtime + assert_equal(t, Time.xmlschema("1999-01-01T00:00:00-00:00"));t.localtime assert_equal(t, Time.xmlschema("1999-01-01T09:00:00+09:00")) assert_equal(t, Time.xmlschema("1999-01-01T01:00:00+01:00")) - assert_equal(t, Time.xmlschema("1999-01-01T00:00:00-00:00")) + assert_equal(t, Time.xmlschema("1999-01-01T00:00:00+00:00")) assert_equal(t, Time.xmlschema("1998-12-31T23:00:00-01:00")) end @@ -468,7 +468,7 @@ typedef struct RNode { #define NOEX_UNDEF NOEX_NOSUPER -#define NOEX_MODFUNC 0x10 +#define NOEX_MODFUNC 0x12 #define NOEX_SUPER 0x20 #define NOEX_VCALL 0x40 @@ -1495,10 +1495,15 @@ num_step(int argc, VALUE *argv, VALUE from) double err = (fabs(beg) + fabs(end) + fabs(end-beg)) / fabs(unit) * epsilon; long i; - if (err>0.5) err=0.5; - n = floor(n + err) + 1; - for (i=0; i<n; i++) { - rb_yield(DBL2NUM(i*unit+beg)); + if (isinf(unit)) { + if (unit > 0) rb_yield(DBL2NUM(beg)); + } + else { + if (err>0.5) err=0.5; + n = floor(n + err) + 1; + for (i=0; i<n; i++) { + rb_yield(DBL2NUM(i*unit+beg)); + } } } else { @@ -969,6 +969,8 @@ void rb_thread_reset_timer_thread(void); (rb_enable_interrupt(), rb_thread_stop_timer_thread()) #define after_exec() \ (rb_thread_start_timer_thread(), rb_disable_interrupt()) +#define before_fork() before_exec() +#define after_fork() after_exec() #include "dln.h" @@ -2275,7 +2277,8 @@ rb_fork(int *status, int (*chfunc)(void*), void *charg, VALUE fds) } } #endif - for (; (pid = fork()) < 0; prefork()) { + for (; before_fork(), (pid = fork()) < 0; prefork()) { + after_fork(); switch (errno) { case EAGAIN: #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN @@ -2301,7 +2304,6 @@ rb_fork(int *status, int (*chfunc)(void*), void *charg, VALUE fds) } } if (!pid) { - rb_thread_reset_timer_thread(); if (chfunc) { #ifdef FD_CLOEXEC close(ep[0]); @@ -2317,10 +2319,10 @@ rb_fork(int *status, int (*chfunc)(void*), void *charg, VALUE fds) _exit(127); #endif } - rb_thread_start_timer_thread(); } + after_fork(); #ifdef FD_CLOEXEC - else if (chfunc) { + if (pid && chfunc) { close(ep[1]); if ((state = read(ep[0], &err, sizeof(err))) < 0) { err = errno; @@ -146,7 +146,7 @@ usage(const char *name) "-T[level] turn on tainting checks", "-v print version number, then turn on verbose mode", "-w turn warnings on for your script", - "-W[level] set warning level; 0=silence, 1=medium, 2=verbose (default)", + "-W[level] set warning level; 0=silence, 1=medium, 2=verbose (default for level)", "-x[directory] strip off text before #!ruby line and perhaps cd to directory", "--copyright print the copyright", "--version print the version", diff --git a/sampledriver/main.c b/sampledriver/main.c index d4633d7faf..9e02eaf865 100644 --- a/sampledriver/main.c +++ b/sampledriver/main.c @@ -28,17 +28,17 @@ */ #include <stdio.h> -#include <ruby/mvm.h> +#include <ruby/vm.h> /* simple interpreter */ static int -simple_driver_example(int argc, const char *argv[]) +simple_driver_example(int argc, char *argv[]) { rb_vm_t *vm; int err; /* create VM with command line options */ - vm = ruby_vm_new(argc-1, argv+1); + vm = ruby_vm_new(argc, argv); /* invoke this VM in current thread (synchronous) */ err = ruby_vm_run(vm); @@ -121,13 +121,21 @@ multivm_driver_example(int argc, const char *argv[]) return 0; } +static const char *pl[] = { + "", + "-E", "utf-8", + "-e", "p [RUBY_PLATFORM, RUBY_VERSION, Encoding::default_external]", + NULL +}; + int main(int argc, char *argv[]) { - RUBY_INITSTACK(); + RUBY_INIT_STACK; ruby_sysinit(&argc, &argv); /* process level initialize */ if (1) { + simple_driver_example(sizeof(pl)/sizeof(pl[0])-1, (char **)pl); return simple_driver_example(argc, argv); } else { @@ -418,7 +418,40 @@ typedef RETSIGTYPE ruby_sigaction_t(int); #endif #ifdef POSIX_SIGNAL -static int +#if defined(SIGSEGV) && defined(HAVE_SIGALTSTACK) +#define USE_SIGALTSTACK +#endif + +#ifdef USE_SIGALTSTACK +#ifdef SIGSTKSZ +#define ALT_STACK_SIZE (SIGSTKSZ*2) +#else +#define ALT_STACK_SIZE (4*1024) +#endif +/* alternate stack for SIGSEGV */ +static void +register_sigaltstack(void) +{ + static void *altstack = 0; + stack_t newSS, oldSS; + + if (altstack) return; + + newSS.ss_sp = altstack = malloc(ALT_STACK_SIZE); + if (newSS.ss_sp == NULL) + /* should handle error */ + rb_bug("register_sigaltstack. malloc error\n"); + newSS.ss_size = ALT_STACK_SIZE; + newSS.ss_flags = 0; + + if (sigaltstack(&newSS, &oldSS) < 0) + rb_bug("register_sigaltstack. error\n"); +} +#else +#define register_sigaltstack() ((void)0) +#endif + +static void ruby_sigaction(int signum, ruby_sigaction_t *handler, int altstack, struct sigaction *old) { struct sigaction sigact; @@ -431,10 +464,6 @@ ruby_sigaction(int signum, ruby_sigaction_t *handler, int altstack, struct sigac #ifdef SA_SIGINFO sigact.sa_sigaction = handler; sigact.sa_flags = SA_SIGINFO; -#ifdef HAVE_SIGALTSTACK - if (altstack) - sigact.sa_flags |= SA_ONSTACK; -#endif #else sigact.sa_handler = (sighandler_t)handler; sigact.sa_flags = 0; @@ -444,7 +473,12 @@ ruby_sigaction(int signum, ruby_sigaction_t *handler, int altstack, struct sigac if (signum == SIGCHLD && (sighandler_t)handler == SIG_IGN) sigact.sa_flags |= SA_NOCLDWAIT; #endif - return sigaction(signum, &sigact, old); +#ifdef SA_ONSTACK + if (altstack) + sigact.sa_flags |= SA_ONSTACK; +#endif + if (sigaction(signum, &sigact, old) < 0) + rb_bug("sigaction error.\n"); } static sighandler_t @@ -464,16 +498,7 @@ posix_signal(int signum, sighandler_t handler) void ruby_install_altstack(rb_thread_t *th) { -#ifdef HAVE_SIGALTSTACK - stack_t sigstk; - static void *segv_stack; - - if (!segv_stack) segv_stack = malloc(SIGSTKSZ * 2); - sigstk.ss_sp = segv_stack; - sigstk.ss_size = SIGSTKSZ; - sigstk.ss_flags = 0; - sigaltstack(&sigstk, 0); -#endif + register_sigaltstack(); } #else /* !POSIX_SIGNAL */ @@ -572,13 +597,12 @@ static int segv_received = 0; static RETSIGTYPE sigsegv(int sig SIGINFO_ARG) { -#ifdef HAVE_SIGALTSTACK +#ifdef USE_SIGALTSTACK int ruby_stack_overflowed_p(const rb_thread_t *, const void *); + NORETURN(void ruby_thread_stack_overflow(rb_thread_t *th)); rb_thread_t *th = GET_THREAD(); if (ruby_stack_overflowed_p(th, info->si_addr)) { - th->errinfo = sysstack_error; - rb_thread_raised_clear(th); - TH_JUMP_TAG(th, TAG_RAISE); + ruby_thread_stack_overflow(th); } #endif if (segv_received) { @@ -715,6 +739,7 @@ default_handler(int sig) #ifdef SIGSEGV case SIGSEGV: func = (sighandler_t)sigsegv; + register_sigaltstack(); break; #endif #ifdef SIGPIPE @@ -1109,8 +1134,8 @@ Init_signal(void) #endif } #ifdef SIGSEGV + register_sigaltstack(); ruby_sigaction(SIGSEGV, sigsegv, Qtrue, NULL); - ruby_install_altstack(GET_THREAD()); #endif #ifdef SIGPIPE install_sighandler(SIGPIPE, sigpipe); diff --git a/strftime.c b/strftime.c index af66fa6377..79c5fe4fa8 100644 --- a/strftime.c +++ b/strftime.c @@ -270,22 +270,37 @@ rb_strftime(char *s, size_t maxsize, const char *format, const struct tm *timept goto unknown; \ } while (0) #define NEEDS(n) do if (s + (n) >= endp - 1) goto err; while (0) +#define FILL_PADDING(i) do { \ + if (!(flags & BIT_OF(LEFT)) && precision > i) { \ + NEEDS(precision); \ + memset(s, padding ? padding : ' ', precision - i); \ + s += precision - i; \ + } \ + else { \ + NEEDS(i); \ + } \ +} while (0); #define FMT(def_pad, def_prec, fmt, val) \ do { \ int l; \ if (precision <= 0) precision = (def_prec); \ if (flags & BIT_OF(LEFT)) precision = 1; \ l = snprintf(s, endp - s, \ - ((padding == '0' || (!padding && def_pad == '0')) ? "%.*"fmt : "%*"fmt), \ + ((padding == '0' || (!padding && def_pad == '0')) ? "%0*"fmt : "%*"fmt), \ precision, val); \ if (l < 0) goto err; \ s += l; \ } while (0) -#define STRFTIME(fmt, tm) \ +#define STRFTIME(fmt) \ do { \ - i = strftime(s, endp - s, fmt, tm); \ + i = rb_strftime(s, endp - s, fmt, timeptr, ts, gmt); \ if (!i) return 0; \ - s += i; \ + if (precision > i) {\ + memmove(s + precision - i, s, i);\ + memset(s, padding ? padding : ' ', precision - i); \ + s += precision; \ + }\ + else s += i; \ } while (0) if (*format != '%') { @@ -300,14 +315,18 @@ rb_strftime(char *s, size_t maxsize, const char *format, const struct tm *timept again: switch (*++format) { case '\0': - *s++ = '%'; - goto out; + format--; + goto unknown; case '%': *s++ = '%'; continue; case 'a': /* abbreviated weekday name */ + if (flags & BIT_OF(CHCASE)) { + flags &= ~(BIT_OF(LOWER)|BIT_OF(CHCASE)); + flags |= BIT_OF(UPPER); + } if (timeptr->tm_wday < 0 || timeptr->tm_wday > 6) i = 1, tp = "?"; else @@ -315,6 +334,10 @@ rb_strftime(char *s, size_t maxsize, const char *format, const struct tm *timept break; case 'A': /* full weekday name */ + if (flags & BIT_OF(CHCASE)) { + flags &= ~(BIT_OF(LOWER)|BIT_OF(CHCASE)); + flags |= BIT_OF(UPPER); + } if (timeptr->tm_wday < 0 || timeptr->tm_wday > 6) i = 1, tp = "?"; else @@ -325,6 +348,10 @@ rb_strftime(char *s, size_t maxsize, const char *format, const struct tm *timept case 'h': /* abbreviated month name */ #endif case 'b': /* abbreviated month name */ + if (flags & BIT_OF(CHCASE)) { + flags &= ~(BIT_OF(LOWER)|BIT_OF(CHCASE)); + flags |= BIT_OF(UPPER); + } if (timeptr->tm_mon < 0 || timeptr->tm_mon > 11) i = 1, tp = "?"; else @@ -332,6 +359,10 @@ rb_strftime(char *s, size_t maxsize, const char *format, const struct tm *timept break; case 'B': /* full month name */ + if (flags & BIT_OF(CHCASE)) { + flags &= ~(BIT_OF(LOWER)|BIT_OF(CHCASE)); + flags |= BIT_OF(UPPER); + } if (timeptr->tm_mon < 0 || timeptr->tm_mon > 11) i = 1, tp = "?"; else @@ -339,7 +370,7 @@ rb_strftime(char *s, size_t maxsize, const char *format, const struct tm *timept break; case 'c': /* appropriate date and time representation */ - STRFTIME("%a %b %e %H:%M:%S %Y", timeptr); + STRFTIME("%a %b %e %H:%M:%S %Y"); continue; case 'd': /* day of the month, 01 - 31 */ @@ -378,7 +409,7 @@ rb_strftime(char *s, size_t maxsize, const char *format, const struct tm *timept case 'p': /* AM or PM based on 12-hour clock */ case 'P': /* am or pm based on 12-hour clock */ if ((*format == 'p' && (flags & BIT_OF(CHCASE))) || - (*format == 'P' && !(flags & BIT_OF(CHCASE)))) { + (*format == 'P' && !(flags & (BIT_OF(CHCASE)|BIT_OF(UPPER))))) { flags &= ~(BIT_OF(UPPER)|BIT_OF(CHCASE)); flags |= BIT_OF(LOWER); } @@ -391,7 +422,7 @@ rb_strftime(char *s, size_t maxsize, const char *format, const struct tm *timept break; case 's': - FMT(' ', 1, "d", (int) ts->tv_sec); + FMT('0', 1, "d", (int) ts->tv_sec); continue; case 'S': /* second, 00 - 60 */ @@ -405,7 +436,7 @@ rb_strftime(char *s, size_t maxsize, const char *format, const struct tm *timept case 'w': /* weekday, Sunday == 0, 0 - 6 */ i = range(0, timeptr->tm_wday, 6); - FMT('0', 0, "d", i); + FMT('0', 1, "d", i); continue; case 'W': /* week of year, Monday is first day of week */ @@ -413,11 +444,11 @@ rb_strftime(char *s, size_t maxsize, const char *format, const struct tm *timept continue; case 'x': /* appropriate date representation */ - STRFTIME("%m/%d/%y", timeptr); + STRFTIME("%m/%d/%y"); continue; case 'X': /* appropriate time representation */ - STRFTIME("%H:%M:%S", timeptr); + STRFTIME("%H:%M:%S"); continue; case 'y': /* year without a century, 00 - 99 */ @@ -426,7 +457,7 @@ rb_strftime(char *s, size_t maxsize, const char *format, const struct tm *timept continue; case 'Y': /* year with century */ - FMT('0', 0, "ld", 1900L + timeptr->tm_year); + FMT('0', 1, "ld", 1900L + timeptr->tm_year); continue; #ifdef MAILHEADER_EXT @@ -540,17 +571,17 @@ rb_strftime(char *s, size_t maxsize, const char *format, const struct tm *timept #ifdef SYSV_EXT case 'n': /* same as \n */ - NEEDS(1); + FILL_PADDING(1); *s++ = '\n'; continue; case 't': /* same as \t */ - NEEDS(1); + FILL_PADDING(1); *s++ = '\t'; continue; case 'D': /* date as %m/%d/%y */ - STRFTIME("%m/%d/%y", timeptr); + STRFTIME("%m/%d/%y"); continue; case 'e': /* day of month, blank padded */ @@ -558,15 +589,15 @@ rb_strftime(char *s, size_t maxsize, const char *format, const struct tm *timept continue; case 'r': /* time as %I:%M:%S %p */ - STRFTIME("%I:%M:%S %p", timeptr); + STRFTIME("%I:%M:%S %p"); continue; case 'R': /* time as %H:%M */ - STRFTIME("%H:%M", timeptr); + STRFTIME("%H:%M"); continue; case 'T': /* time as %H:%M:%S */ - STRFTIME("%H:%M:%S", timeptr); + STRFTIME("%H:%M:%S"); continue; #endif @@ -623,7 +654,7 @@ rb_strftime(char *s, size_t maxsize, const char *format, const struct tm *timept case 'u': /* ISO 8601: Weekday as a decimal number [1 (Monday) - 7] */ - FMT('0', 0, "d", timeptr->tm_wday == 0 ? 7 : timeptr->tm_wday); + FMT('0', 1, "d", timeptr->tm_wday == 0 ? 7 : timeptr->tm_wday); continue; #endif /* POSIX2_DATE */ @@ -648,7 +679,7 @@ rb_strftime(char *s, size_t maxsize, const char *format, const struct tm *timept y = 1900L + timeptr->tm_year; if (*format == 'G') - FMT('0', 0, "ld", y); + FMT('0', 1, "ld", y); else FMT('0', 2, "ld", y % 100); continue; @@ -673,8 +704,7 @@ rb_strftime(char *s, size_t maxsize, const char *format, const struct tm *timept { long n = ts->tv_nsec; - if (precision == 0) continue; - if (precision < 0) { + if (precision <= 0) { precision = w; } NEEDS(precision); @@ -737,19 +767,15 @@ rb_strftime(char *s, size_t maxsize, const char *format, const struct tm *timept default: unknown: - tp = sp; i = format - sp + 1; + tp = sp; + precision = -1; + flags = 0; + padding = 0; break; } if (i) { - if (!(flags & BIT_OF(LEFT)) && precision > i) { - NEEDS(precision); - memset(s, padding ? padding : ' ', precision - i); - s += precision - i; - } - else { - NEEDS(i); - } + FILL_PADDING(i); memcpy(s, tp, i); switch (flags & (BIT_OF(UPPER)|BIT_OF(LOWER))) { case BIT_OF(UPPER): @@ -768,7 +794,6 @@ rb_strftime(char *s, size_t maxsize, const char *format, const struct tm *timept } } } -out: if (s >= endp) { goto err; } diff --git a/test/bigdecimal/test_bigdecimal.rb b/test/bigdecimal/test_bigdecimal.rb index 35edc7a44a..d129d93068 100644 --- a/test/bigdecimal/test_bigdecimal.rb +++ b/test/bigdecimal/test_bigdecimal.rb @@ -77,6 +77,7 @@ class TestBigDecimal < Test::Unit::TestCase end def test_exception_zerodivide + BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false) _test_mode(BigDecimal::EXCEPTION_ZERODIVIDE) { 1 / BigDecimal.new("0") } _test_mode(BigDecimal::EXCEPTION_ZERODIVIDE) { -1 / BigDecimal.new("0") } end @@ -275,6 +276,7 @@ class TestBigDecimal < Test::Unit::TestCase def test_finite_infinite_nan BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false) + BigDecimal.mode(BigDecimal::EXCEPTION_ZERODIVIDE, false) x = BigDecimal.new("0") assert_equal(true, x.finite?) @@ -303,9 +305,9 @@ class TestBigDecimal < Test::Unit::TestCase x = BigDecimal.new("0") assert_kind_of(Integer, x.to_i) assert_equal(0, x.to_i) - assert_nil(( 1 / x).to_i) - assert_nil((-1 / x).to_i) - assert_nil(( 0 / x).to_i) + assert_raise(FloatDomainError){( 1 / x).to_i} + assert_raise(FloatDomainError){(-1 / x).to_i} + assert_raise(FloatDomainError) {( 0 / x).to_i} x = BigDecimal.new("1") assert_equal(1, x.to_i) x = BigDecimal.new((2**100).to_s) @@ -315,6 +317,7 @@ class TestBigDecimal < Test::Unit::TestCase def test_to_f BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false) BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false) + BigDecimal.mode(BigDecimal::EXCEPTION_ZERODIVIDE, false) x = BigDecimal.new("0") assert_instance_of(Float, x.to_f) @@ -616,6 +619,7 @@ class TestBigDecimal < Test::Unit::TestCase def test_sign BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false) BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false) + BigDecimal.mode(BigDecimal::EXCEPTION_ZERODIVIDE, false) assert_equal(BigDecimal::SIGN_POSITIVE_ZERO, BigDecimal.new("0").sign) assert_equal(BigDecimal::SIGN_NEGATIVE_ZERO, BigDecimal.new("-0").sign) diff --git a/test/cgi/test_cgi_session.rb b/test/cgi/test_cgi_session.rb index c041b9cf59..d5120b933c 100644 --- a/test/cgi/test_cgi_session.rb +++ b/test/cgi/test_cgi_session.rb @@ -3,19 +3,18 @@ require 'cgi' require 'cgi/session' require 'cgi/session/pstore' require 'stringio' +require 'tmpdir' class CGISessionTest < Test::Unit::TestCase - - def setup - FileUtils.rm(Dir::glob(File.dirname(__FILE__)+"/session_dir/*")) + @session_dir = Dir.mktmpdir('__test_dir__')+'/session_dir/' + FileUtils.mkdir_p @session_dir end - def teardown @environ.each do |key, val| ENV.delete(key) end $stdout = STDOUT -# FileUtils.rm(Dir::glob(File.dirname(__FILE__)+"/session_dir/*")) + FileUtils.rm_rf(@session_dir) end def test_cgi_session_filestore @@ -31,7 +30,7 @@ class CGISessionTest < Test::Unit::TestCase value2.force_encoding("SJIS") if RUBY_VERSION>="1.9" ENV.update(@environ) cgi = CGI.new - session = CGI::Session.new(cgi,"tmpdir"=>File.dirname(__FILE__)+"/session_dir") + session = CGI::Session.new(cgi,"tmpdir"=>@session_dir) session["key1"]=value1 session["key2"]=value2 assert_equal(value1,session["key1"]) @@ -49,7 +48,7 @@ class CGISessionTest < Test::Unit::TestCase } ENV.update(@environ) cgi = CGI.new - session = CGI::Session.new(cgi,"tmpdir"=>File.dirname(__FILE__)+"/session_dir") + session = CGI::Session.new(cgi,"tmpdir"=>@session_dir) $stdout = StringIO.new assert_equal(value1,session["key1"]) assert_equal(value2,session["key2"]) @@ -69,7 +68,7 @@ class CGISessionTest < Test::Unit::TestCase value2.force_encoding("SJIS") if RUBY_VERSION>="1.9" ENV.update(@environ) cgi = CGI.new - session = CGI::Session.new(cgi,"tmpdir"=>File.dirname(__FILE__)+"/session_dir","database_manager"=>CGI::Session::PStore) + session = CGI::Session.new(cgi,"tmpdir"=>@session_dir,"database_manager"=>CGI::Session::PStore) session["key1"]=value1 session["key2"]=value2 assert_equal(value1,session["key1"]) @@ -87,7 +86,7 @@ class CGISessionTest < Test::Unit::TestCase } ENV.update(@environ) cgi = CGI.new - session = CGI::Session.new(cgi,"tmpdir"=>File.dirname(__FILE__)+"/session_dir","database_manager"=>CGI::Session::PStore) + session = CGI::Session.new(cgi,"tmpdir"=>@session_dir,"database_manager"=>CGI::Session::PStore) $stdout = StringIO.new assert_equal(value1,session["key1"]) assert_equal(value2,session["key2"]) diff --git a/test/date/test_date.rb b/test/date/test_date.rb index de7e4838c3..f2be9e24c4 100644 --- a/test/date/test_date.rb +++ b/test/date/test_date.rb @@ -41,9 +41,9 @@ class TestDate < Test::Unit::TestCase assert_instance_of(DateSub, DateSub.today) assert_instance_of(DateTimeSub, DateTimeSub.now) - assert_equal('#<DateSub: -1/2,0,2299161>', d.inspect) + assert_equal('#<DateSub: -4712-01-01 (-1/2,0,2299161)>', d.inspect) assert_equal('-4712-01-01', d.to_s) - assert_equal('#<DateTimeSub: -1/2,0,2299161>', dt.inspect) + assert_equal('#<DateTimeSub: -4712-01-01T00:00:00+00:00 (-1/2,0,2299161)>', dt.inspect) assert_equal('-4712-01-01T00:00:00+00:00', dt.to_s) d2 = d + 1 diff --git a/test/date/test_date_attr.rb b/test/date/test_date_attr.rb index 2e71b5f501..5187d5d3e5 100644 --- a/test/date/test_date_attr.rb +++ b/test/date/test_date_attr.rb @@ -9,10 +9,10 @@ class TestDateAttr < Test::Unit::TestCase [date, datetime].each_with_index do |d, i| if i == 0 - assert_match(/\#<Date\d?: 4877807\/2,0,2299161>/, + assert_match(/\#<Date\d?: 1965-05-23 \(4877807\/2,0,2299161\)>/, d.inspect) else - assert_match(/\#<DateTime\d?: 210721343519\/86400,0,2299161>/, + assert_match(/\#<DateTime\d?: 1965-05-23T22:31:59\+00:00 \(210721343519\/86400,0,2299161\)>/, d.inspect) end diff --git a/test/date/test_date_strftime.rb b/test/date/test_date_strftime.rb index 1a190f21cc..4131af3aab 100644 --- a/test/date/test_date_strftime.rb +++ b/test/date/test_date_strftime.rb @@ -299,6 +299,24 @@ class TestDateStrftime < Test::Unit::TestCase assert_equal('-2000', d.strftime('%05Y')) end + def test_strftime__gnuext_LN # coreutils + d = DateTime.parse('2008-11-25T00:11:22.0123456789') + assert_equal('012', d.strftime('%L')) + assert_equal('012', d.strftime('%0L')) + assert_equal('0', d.strftime('%1L')) + assert_equal('01', d.strftime('%2L')) + assert_equal('01234567890', d.strftime('%11L')) + assert_equal('01234567890', d.strftime('%011L')) + assert_equal('01234567890', d.strftime('%_11L')) + assert_equal('012345678', d.strftime('%N')) + assert_equal('012345678', d.strftime('%0N')) + assert_equal('0', d.strftime('%1N')) + assert_equal('01', d.strftime('%2N')) + assert_equal('01234567890', d.strftime('%11N')) + assert_equal('01234567890', d.strftime('%011N')) + assert_equal('01234567890', d.strftime('%_11N')) + end + def test_strftime__gnuext_z # coreutils d = DateTime.parse('2006-08-08T23:15:33+09:08:07') assert_equal('+0908', d.strftime('%z')) diff --git a/test/ruby/test_method.rb b/test/ruby/test_method.rb index d978050dc8..1546ce3287 100644 --- a/test/ruby/test_method.rb +++ b/test/ruby/test_method.rb @@ -27,6 +27,15 @@ class TestMethod < Test::Unit::TestCase class Derived < Base def foo() :derived end end + class T + def initialize; end + def normal_method; end + end + module M + def func; end + module_function :func + def meth; end + end def test_arity assert_equal(0, method(:m0).arity) @@ -221,4 +230,11 @@ class TestMethod < Test::Unit::TestCase assert_raise(ArgumentError) { o.method(:foo=).call(1, 2, 3) } assert_raise(ArgumentError) { o.method(:foo).call(1) } end + + def test_default_accessibility + assert T.public_instance_methods.include?(:normal_method), 'normal methods are public by default' + assert !T.public_instance_methods.include?(:initialize), '#initialize is private' + assert !M.public_instance_methods.include?(:func), 'module methods are private by default' + assert M.public_instance_methods.include?(:meth), 'normal methods are public by default' + end end diff --git a/test/ruby/test_time.rb b/test/ruby/test_time.rb index 3a9b055802..a1a5bfc7fb 100644 --- a/test/ruby/test_time.rb +++ b/test/ruby/test_time.rb @@ -396,7 +396,7 @@ class TestTime < Test::Unit::TestCase assert_equal("123456", t.strftime("%6N")) assert_equal("123456789", t.strftime("%9N")) assert_equal("1234567890", t.strftime("%10N")) - assert_equal("", t.strftime("%0N")) + assert_equal("123456789", t.strftime("%0N")) assert_equal("000", t.strftime("%3S")) assert_equal("946684800", t.strftime("%s")) assert_equal("946684800", t.utc.strftime("%s")) @@ -444,5 +444,29 @@ class TestTime < Test::Unit::TestCase assert_equal(" 2", t.strftime("%l")) assert_equal("02", t.strftime("%0l")) assert_equal(" 2", t.strftime("%_l")) + + # [ruby-dev:37155] + t = Time.mktime(1970, 1, 18) + assert_equal("0", t.strftime("%w")) + assert_equal("7", t.strftime("%u")) + + # [ruby-dev:37160] + assert_equal("\t", T2000.strftime("%t")) + assert_equal("\t", T2000.strftime("%0t")) + assert_equal("\t", T2000.strftime("%1t")) + assert_equal(" \t", T2000.strftime("%3t")) + assert_equal("00\t", T2000.strftime("%03t")) + assert_equal("\n", T2000.strftime("%n")) + assert_equal("\n", T2000.strftime("%0n")) + assert_equal("\n", T2000.strftime("%1n")) + assert_equal(" \n", T2000.strftime("%3n")) + assert_equal("00\n", T2000.strftime("%03n")) + + # [ruby-dev:37162] + assert_equal("SAT", T2000.strftime("%#a")) + assert_equal("SATURDAY", T2000.strftime("%#A")) + assert_equal("JAN", T2000.strftime("%#b")) + assert_equal("JANUARY", T2000.strftime("%#B")) + assert_equal("JAN", T2000.strftime("%#h")) end end diff --git a/test/yaml/test_yaml.rb b/test/yaml/test_yaml.rb index ed94705fcf..837f34722f 100644 --- a/test/yaml/test_yaml.rb +++ b/test/yaml/test_yaml.rb @@ -1306,6 +1306,10 @@ EOY raise "id collision in ordered map" if omap.to_yaml =~ /id\d+/ end + def test_date_out_of_range + assert_nothing_raised{YAML::load('1900-01-01T00:00:00+00:00')} + end + def test_normal_exit YAML.load("2000-01-01 00:00:00.#{"0"*1000} +00:00\n") # '[ruby-core:13735]' @@ -1268,6 +1268,14 @@ rb_thread_signal_exit(void *thptr) rb_thread_raise(2, argv, th->vm->main_thread); } +void +ruby_thread_stack_overflow(rb_thread_t *th) +{ + th->errinfo = sysstack_error; + th->raised_flag = 0; + TH_JUMP_TAG(th, TAG_RAISE); +} + int rb_thread_set_raised(rb_thread_t *th) { @@ -2489,6 +2497,7 @@ rb_thread_reset_timer_thread(void) void rb_thread_start_timer_thread(void) { + system_working = 1; rb_thread_create_timer_thread(); } @@ -1,7 +1,7 @@ #define RUBY_VERSION "1.9.0" -#define RUBY_RELEASE_DATE "2008-11-19" +#define RUBY_RELEASE_DATE "2008-11-27" #define RUBY_VERSION_CODE 190 -#define RUBY_RELEASE_CODE 20081119 +#define RUBY_RELEASE_CODE 20081127 #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 11 -#define RUBY_RELEASE_DAY 19 +#define RUBY_RELEASE_DAY 27 #ifdef RUBY_EXTERN RUBY_EXTERN const char ruby_version[]; @@ -1478,7 +1478,7 @@ thread_free(void *ptr) rb_queue_destroy(&th->queue.message); rb_queue_destroy(&th->queue.signal); - if (th->vm->main_thread == th) { + if (th->vm && th->vm->main_thread == th) { RUBY_GC_INFO("main thread\n"); } else { |