From b3144a7a0e08500d212c9f30e889dfcff631fbc4 Mon Sep 17 00:00:00 2001 From: matz Date: Mon, 3 Dec 2001 10:07:48 +0000 Subject: * time.c (time_plus): must detect result overflow. * time.c (time_minus): ditto. * time.c (time_new_internal): round usec overflow and underflow here. * time.c (time_plus): move operand overflow/underflow check to time_new_internal(). * time.c (time_minus): ditto. * time.c (time_cmp): should consider tv_usec too. * time.c (time_gmtime): time_modify() should be called even if tm struct is not calculated yet. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@1880 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 22 ++++++++++- lib/singleton.rb | 110 ++++++++++++++++++++++++++++--------------------------- time.c | 62 +++++++++++++++++++------------ 3 files changed, 117 insertions(+), 77 deletions(-) diff --git a/ChangeLog b/ChangeLog index 1df1d62966..d978c35d60 100644 --- a/ChangeLog +++ b/ChangeLog @@ -8,6 +8,22 @@ Mon Dec 3 16:04:16 2001 Usaku Nakamura * configure.in: not use X11BASE, since it's not always set. +Mon Dec 3 09:59:08 2001 Yukihiro Matsumoto + + * time.c (time_plus): must detect result overflow. + + * time.c (time_minus): ditto. + + * time.c (time_new_internal): round usec overflow and underflow + here. + + * time.c (time_plus): move operand overflow/underflow check to + time_new_internal(). + + * time.c (time_minus): ditto. + + * time.c (time_cmp): should consider tv_usec too. + Mon Dec 3 03:32:22 2001 Usaku Nakamura * configure.in: apply patch from NetBSD's pkgsrc (patch-aa). @@ -20,6 +36,11 @@ Sun Dec 2 22:01:52 2001 WATANABE Hirofumi * ext/dbm/extconf.rb: check if $CFLAGS includes DBM_HDR. +Sat Dec 1 12:13:20 2001 Yukihiro Matsumoto + + * time.c (time_gmtime): time_modify() should be called even if tm + struct is not calculated yet. + Fri Nov 30 17:02:55 2001 WATANABE Hirofumi * configure.in: set target_cpu to i386 on cygwin and mingw32. @@ -13145,4 +13166,3 @@ Fri Aug 15 19:40:43 1997 WATANABE Hirofumi Wed Aug 13 17:51:46 1997 Yukihiro Matsumoto * version 1.1 alpha0 released. - diff --git a/lib/singleton.rb b/lib/singleton.rb index 3ab048f5a3..404eaf7101 100644 --- a/lib/singleton.rb +++ b/lib/singleton.rb @@ -44,60 +44,64 @@ # of a previous state of ``the instance'' - see third example. # module Singleton - def Singleton.included (klass) - # should this be checked? - # raise TypeError.new "..." if klass.type == Module - class << klass - def inherited(sub_klass) - # @__instance__ takes on one of the following values - # * nil - before (and after a failed) creation - # * false - during creation - # * sub_class instance - after a successful creation - sub_klass.instance_eval { @__instance__ = nil } - def sub_klass.instance - unless @__instance__.nil? - # is the extra flexiblity having the hook method - # _wait() around ever useful? - _wait() - # check for instance creation - return @__instance__ if @__instance__ - end - Thread.critical = true - unless @__instance__ - @__instance__ = false - Thread.critical = false - begin - @__instance__ = new - ensure - if @__instance__ - define_method(:instance) {@__instance__ } - else - # failed instance creation - @__instance__ = nil - end - end - else - Thread.critical = false - end - return @__instance__ - end - end - def _load(str) - instance - end - def _wait - sleep(0.05) while false.equal?(@__instance__) - end - private :new, :allocate - # hook methods are also marked private - private :_load,:_wait - end - klass.inherited klass - end - private - def _dump(depth) - return "" + def Singleton.included (klass) + # should this be checked? + # raise TypeError.new "..." if klass.type == Module + klass.module_eval { + undef_method :clone + undef_method :dup + } + class << klass + def inherited(sub_klass) + # @__instance__ takes on one of the following values + # * nil - before (and after a failed) creation + # * false - during creation + # * sub_class instance - after a successful creation + sub_klass.instance_eval { @__instance__ = nil } + def sub_klass.instance + unless @__instance__.nil? + # is the extra flexiblity having the hook method + # _wait() around ever useful? + _wait() + # check for instance creation + return @__instance__ if @__instance__ + end + Thread.critical = true + unless @__instance__ + @__instance__ = false + Thread.critical = false + begin + @__instance__ = new + ensure + if @__instance__ + define_method(:instance) {@__instance__ } + else + # failed instance creation + @__instance__ = nil + end + end + else + Thread.critical = false + end + return @__instance__ + end + end + def _load(str) + instance + end + def _wait + sleep(0.05) while false.equal?(@__instance__) + end + private :new, :allocate + # hook methods are also marked private + private :_load,:_wait end + klass.inherited klass + end + private + def _dump(depth) + return "" + end end if __FILE__ == $0 diff --git a/time.c b/time.c index e01f99fca5..35ef208802 100644 --- a/time.c +++ b/time.c @@ -68,6 +68,14 @@ time_new_internal(klass, sec, usec) VALUE obj; struct time_object *tobj; + if (usec >= 1000000) { /* usec overflow */ + sec += usec / 1000000; + usec %= 1000000; + } + if (usec < 0) { /* usec underflow */ + sec -= (-usec) / 1000000; + usec %= 1000000; + } #ifndef NEGATIVE_TIME_T if (sec < 0 || (sec == 0 && usec < 0)) rb_raise(rb_eArgError, "time must be positive"); @@ -601,7 +609,13 @@ time_cmp(time1, time2) switch (TYPE(time2)) { case T_FIXNUM: i = FIX2LONG(time2); - if (tobj1->tv.tv_sec == i) return INT2FIX(0); + if (tobj1->tv.tv_sec == i) { + if (tobj1->tv.tv_usec == 0) + return INT2FIX(0); + if (tobj1->tv.tv_usec > 0) + return INT2FIX(1); + return INT2FIX(-1); + } if (tobj1->tv.tv_sec > i) return INT2FIX(1); return INT2FIX(-1); @@ -706,8 +720,11 @@ time_localtime(time) time_t t; GetTimeval(time, tobj); - if (tobj->tm_got) { - if (!tobj->gmt) return time; + if (!tobj->gmt) { + if (tobj->tm_got) + return time; + } + else { time_modify(time); } t = tobj->tv.tv_sec; @@ -727,8 +744,11 @@ time_gmtime(time) time_t t; GetTimeval(time, tobj); - if (tobj->tm_got) { - if (tobj->gmt) return time; + if (tobj->gmt) { + if (tobj->tm_got) + return time; + } + else { time_modify(time); } t = tobj->tv.tv_sec; @@ -804,14 +824,12 @@ time_plus(time1, time2) usec = tobj->tv.tv_usec + (time_t)((f - (double)sec)*1e6); sec = tobj->tv.tv_sec + sec; - if (usec >= 1000000) { /* usec overflow */ - sec++; - usec -= 1000000; - } - if (usec < 0) { /* usec underflow */ - sec--; - usec += 1000000; +#ifdef NEGATIVE_TIME_T + if ((tobj->tv.tv_sec > 0 && f > 0 && sec < 0) || + (tobj->tv.tv_sec < 0 && f < 0 && sec > 0)) { + rb_raise(rb_eRangeError, "time + %f out of Time range", f); } +#endif time2 = rb_time_new(sec, usec); if (tobj->gmt) { GetTimeval(time2, tobj); @@ -833,8 +851,8 @@ time_minus(time1, time2) struct time_object *tobj2; GetTimeval(time2, tobj2); - f = tobj->tv.tv_sec - tobj2->tv.tv_sec; - f += (tobj->tv.tv_usec - tobj2->tv.tv_usec)*1e-6; + f = (double)tobj->tv.tv_sec - (double)tobj2->tv.tv_sec; + f += ((double)tobj->tv.tv_usec - (double)tobj2->tv.tv_usec)*1e-6; return rb_float_new(f); } @@ -844,16 +862,14 @@ time_minus(time1, time2) usec = tobj->tv.tv_usec - (time_t)((f - (double)sec)*1e6); sec = tobj->tv.tv_sec - sec; } - - if (usec >= 1000000) { /* usec overflow */ - sec++; - usec -= 1000000; - } - if (usec < 0) { /* usec underflow */ - sec--; - usec += 1000000; +#ifdef NEGATIVE_TIME_T + if ((tobj->tv.tv_sec < 0 && f > 0 && sec > 0) || + (tobj->tv.tv_sec > 0 && f < 0 && sec < 0)) { + rb_raise(rb_eRangeError, "time - %f out of Time range", f); } - time2 = time_new_internal(rb_obj_class(time1), sec, usec); +#endif + + time2 = rb_time_new(sec, usec); if (tobj->gmt) { GetTimeval(time2, tobj); tobj->gmt = 1; -- cgit v1.2.3