From 0fb0d42369a02071e2dec4fb3cfd137262b192f1 Mon Sep 17 00:00:00 2001 From: matz Date: Thu, 24 May 2001 06:10:36 +0000 Subject: * eval.c (rb_yield_0): need argument adjustment for C defined blocks too. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@1444 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 14 ++++ eval.c | 7 ++ ext/dbm/dbm.c | 90 ++++++++++----------- ext/extmk.rb.in | 3 +- parse.y | 5 -- time.c | 244 +++++++++++++++++++++++++++++++++++--------------------- version.h | 4 +- 7 files changed, 224 insertions(+), 143 deletions(-) diff --git a/ChangeLog b/ChangeLog index ca161b279b..278d921693 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,17 @@ +Thu May 24 14:23:35 2001 Yukihiro Matsumoto + + * eval.c (rb_yield_0): need argument adjustment for C defined + blocks too. + +Thu May 24 01:11:30 2001 Yukihiro Matsumoto + + * ext/dbm/extconf.rb: header search added. [new] + +Wed May 23 02:58:21 2001 Tanaka Akira + + * time.c (make_time_t): fix ad-hoc local time adjustment, using + binary tree search. + Tue May 22 17:10:35 2001 K.Kosako * variable.c (rb_alias_variable): should not allow variable diff --git a/eval.c b/eval.c index 5116e90347..cc21c7c606 100644 --- a/eval.c +++ b/eval.c @@ -3608,6 +3608,13 @@ rb_yield_0(val, self, klass, acheck) POP_TAG(); if (state) goto pop_state; } + else { + /* argument adjust for proc_call etc. */ + if (acheck && val != Qundef && + TYPE(val) == T_ARRAY && RARRAY(val)->len == 1) { + val = RARRAY(val)->ptr[0]; + } + } PUSH_ITER(block->iter); PUSH_TAG(PROT_NONE); diff --git a/ext/dbm/dbm.c b/ext/dbm/dbm.c index 062ae692ab..55e207c49a 100644 --- a/ext/dbm/dbm.c +++ b/ext/dbm/dbm.c @@ -18,11 +18,11 @@ #ifdef HAVE_SYS_CDEFS_H # include #endif -#include +#include DBM_HDR #include #include -VALUE cDBM, rb_eDBMError; +static VALUE rb_cDBM, rb_eDBMError; struct dbmdata { int di_size; @@ -675,48 +675,48 @@ fdbm_reject(obj) void Init_dbm() { - cDBM = rb_define_class("DBM", rb_cObject); + rb_cDBM = rb_define_class("DBM", rb_cObject); rb_eDBMError = rb_define_class("DBMError", rb_eStandardError); - rb_include_module(cDBM, rb_mEnumerable); - - rb_define_singleton_method(cDBM, "new", fdbm_s_new, -1); - rb_define_singleton_method(cDBM, "open", fdbm_s_open, -1); - - rb_define_method(cDBM, "initialize", fdbm_initialize, -1); - rb_define_method(cDBM, "close", fdbm_close, 0); - rb_define_method(cDBM, "[]", fdbm_aref, 1); - rb_define_method(cDBM, "fetch", fdbm_fetch_m, -1); - rb_define_method(cDBM, "[]=", fdbm_store, 2); - rb_define_method(cDBM, "store", fdbm_store, 2); - rb_define_method(cDBM, "index", fdbm_index, 1); - rb_define_method(cDBM, "indexes", fdbm_indexes, -1); - rb_define_method(cDBM, "indices", fdbm_indexes, -1); - rb_define_method(cDBM, "length", fdbm_length, 0); - rb_define_alias(cDBM, "size", "length"); - rb_define_method(cDBM, "empty?", fdbm_empty_p, 0); - rb_define_method(cDBM, "each", fdbm_each_pair, 0); - rb_define_method(cDBM, "each_value", fdbm_each_value, 0); - rb_define_method(cDBM, "each_key", fdbm_each_key, 0); - rb_define_method(cDBM, "each_pair", fdbm_each_pair, 0); - rb_define_method(cDBM, "keys", fdbm_keys, 0); - rb_define_method(cDBM, "values", fdbm_values, 0); - rb_define_method(cDBM, "shift", fdbm_shift, 0); - rb_define_method(cDBM, "delete", fdbm_delete, 1); - rb_define_method(cDBM, "delete_if", fdbm_delete_if, 0); - rb_define_method(cDBM, "reject!", fdbm_delete_if, 0); - rb_define_method(cDBM, "reject", fdbm_reject, 0); - rb_define_method(cDBM, "clear", fdbm_clear, 0); - rb_define_method(cDBM,"invert", fdbm_invert, 0); - rb_define_method(cDBM,"update", fdbm_update, 1); - rb_define_method(cDBM,"replace", fdbm_replace, 1); - - rb_define_method(cDBM, "include?", fdbm_has_key, 1); - rb_define_method(cDBM, "has_key?", fdbm_has_key, 1); - rb_define_method(cDBM, "member?", fdbm_has_key, 1); - rb_define_method(cDBM, "has_value?", fdbm_has_value, 1); - rb_define_method(cDBM, "key?", fdbm_has_key, 1); - rb_define_method(cDBM, "value?", fdbm_has_value, 1); - - rb_define_method(cDBM, "to_a", fdbm_to_a, 0); - rb_define_method(cDBM, "to_hash", fdbm_to_hash, 0); + rb_include_module(rb_cDBM, rb_mEnumerable); + + rb_define_singleton_method(rb_cDBM, "new", fdbm_s_new, -1); + rb_define_singleton_method(rb_cDBM, "open", fdbm_s_open, -1); + + rb_define_method(rb_cDBM, "initialize", fdbm_initialize, -1); + rb_define_method(rb_cDBM, "close", fdbm_close, 0); + rb_define_method(rb_cDBM, "[]", fdbm_aref, 1); + rb_define_method(rb_cDBM, "fetch", fdbm_fetch_m, -1); + rb_define_method(rb_cDBM, "[]=", fdbm_store, 2); + rb_define_method(rb_cDBM, "store", fdbm_store, 2); + rb_define_method(rb_cDBM, "index", fdbm_index, 1); + rb_define_method(rb_cDBM, "indexes", fdbm_indexes, -1); + rb_define_method(rb_cDBM, "indices", fdbm_indexes, -1); + rb_define_method(rb_cDBM, "length", fdbm_length, 0); + rb_define_method(rb_cDBM, "size", fdbm_length, 0); + rb_define_method(rb_cDBM, "empty?", fdbm_empty_p, 0); + rb_define_method(rb_cDBM, "each", fdbm_each_pair, 0); + rb_define_method(rb_cDBM, "each_value", fdbm_each_value, 0); + rb_define_method(rb_cDBM, "each_key", fdbm_each_key, 0); + rb_define_method(rb_cDBM, "each_pair", fdbm_each_pair, 0); + rb_define_method(rb_cDBM, "keys", fdbm_keys, 0); + rb_define_method(rb_cDBM, "values", fdbm_values, 0); + rb_define_method(rb_cDBM, "shift", fdbm_shift, 0); + rb_define_method(rb_cDBM, "delete", fdbm_delete, 1); + rb_define_method(rb_cDBM, "delete_if", fdbm_delete_if, 0); + rb_define_method(rb_cDBM, "reject!", fdbm_delete_if, 0); + rb_define_method(rb_cDBM, "reject", fdbm_reject, 0); + rb_define_method(rb_cDBM, "clear", fdbm_clear, 0); + rb_define_method(rb_cDBM,"invert", fdbm_invert, 0); + rb_define_method(rb_cDBM,"update", fdbm_update, 1); + rb_define_method(rb_cDBM,"replace", fdbm_replace, 1); + + rb_define_method(rb_cDBM, "include?", fdbm_has_key, 1); + rb_define_method(rb_cDBM, "has_key?", fdbm_has_key, 1); + rb_define_method(rb_cDBM, "member?", fdbm_has_key, 1); + rb_define_method(rb_cDBM, "has_value?", fdbm_has_value, 1); + rb_define_method(rb_cDBM, "key?", fdbm_has_key, 1); + rb_define_method(rb_cDBM, "value?", fdbm_has_value, 1); + + rb_define_method(rb_cDBM, "to_a", fdbm_to_a, 0); + rb_define_method(rb_cDBM, "to_hash", fdbm_to_hash, 0); } diff --git a/ext/extmk.rb.in b/ext/extmk.rb.in index 9e454cc429..d57ff2f9f9 100644 --- a/ext/extmk.rb.in +++ b/ext/extmk.rb.in @@ -280,8 +280,7 @@ def have_header(header) SRC return false end - header.tr!("a-z./\055", "A-Z___") - $defs.push(format("-DHAVE_%s", header)) + $defs.push(format("-DHAVE_%s", header.tr("a-z./\055", "A-Z___"))) return true end diff --git a/parse.y b/parse.y index 94df4497e2..51b04288c0 100644 --- a/parse.y +++ b/parse.y @@ -1394,11 +1394,6 @@ opt_block_var : none { $$ = $2; } - | '<' f_args '>' - { - $$ = (NODE*)2; - } - do_block : kDO_BLOCK { diff --git a/time.c b/time.c index dd3b6eb666..49aba76858 100644 --- a/time.c +++ b/time.c @@ -286,108 +286,174 @@ static VALUE time_gmtime _((VALUE)); static VALUE time_localtime _((VALUE)); static VALUE time_get_tm _((VALUE, int)); +static int +tmcmp(a, b) + struct tm *a; + struct tm *b; +{ + if (a->tm_year != b->tm_year) + return a->tm_year < b->tm_year ? -1 : 1; + else if (a->tm_mon != b->tm_mon) + return a->tm_mon < b->tm_mon ? -1 : 1; + else if (a->tm_mday != b->tm_mday) + return a->tm_mday < b->tm_mday ? -1 : 1; + else if (a->tm_hour != b->tm_hour) + return a->tm_hour < b->tm_hour ? -1 : 1; + else if (a->tm_min != b->tm_min) + return a->tm_min < b->tm_min ? -1 : 1; + else if (a->tm_sec != b->tm_sec) + return a->tm_sec < b->tm_sec ? -1 : 1; + else + return 0; +} + static time_t make_time_t(tptr, utc_p) struct tm *tptr; int utc_p; { - struct timeval tv; - time_t oguess, guess; - struct tm *tm; - long t, diff, i; + time_t guess, guess_lo, guess_hi; + struct tm *tm, tm_lo, tm_hi; + int d; - if (gettimeofday(&tv, 0) < 0) { - rb_sys_fail("gettimeofday"); - } - guess = tv.tv_sec; +#ifdef NEGATIVE_TIME_T + guess_lo = 1 << (8 * sizeof(time_t) - 1); +#else + guess_lo = 0; +#endif + guess_hi = ((time_t)-1) < ((time_t)0) ? + (1U << (8 * sizeof(time_t) - 1)) - 1 : + ~(time_t)0; - tm = gmtime(&guess); + tm = (utc_p ? gmtime : localtime)(&guess_lo); if (!tm) goto error; - t = tptr->tm_year; -#ifndef NEGATIVE_TIME_T - if (t < 69) goto out_of_range; -#endif - i = 0; - while (diff = t - tm->tm_year) { - guess += diff * 363 * 24 * 3600; - if (i++ > 255) goto out_of_range; - tm = gmtime(&guess); - if (!tm) goto error; - } - t = tptr->tm_mon; - while (diff = t - tm->tm_mon) { - guess += diff * 27 * 24 * 3600; - tm = gmtime(&guess); - if (!tm) goto error; - if (tptr->tm_year != tm->tm_year) goto out_of_range; - } - oguess = guess; - guess += (tptr->tm_mday - tm->tm_mday) * 24 * 3600; - guess += (tptr->tm_hour - tm->tm_hour) * 3600; - guess += (tptr->tm_min - tm->tm_min) * 60; - guess += (tptr->tm_sec - tm->tm_sec); -#ifndef NEGATIVE_TIME_T - if (guess < 0) goto out_of_range; -#endif + d = tmcmp(tptr, tm); + if (d < 0) goto out_of_range; + if (d == 0) return guess_lo; + tm_lo = *tm; - if (!utc_p) { /* localtime zone adjust */ - struct tm gt, lt; - long tzsec; - - t = 0; - tm = gmtime(&guess); - if (!tm) goto error; - gt = *tm; - tm = localtime(&guess); - if (!tm) goto error; - lt = *tm; - tzsec = (gt.tm_min-lt.tm_min)*60 + (gt.tm_hour-lt.tm_hour)*3600; - - if (lt.tm_year > gt.tm_year) { - tzsec -= 24*3600; - } - else if(gt.tm_year > lt.tm_year) { - tzsec += 24*3600; - } - else { - tzsec += (gt.tm_yday - lt.tm_yday)*24*3600; + tm = (utc_p ? gmtime : localtime)(&guess_hi); + if (!tm) goto error; + d = tmcmp(tptr, tm); + if (d > 0) goto out_of_range; + if (d == 0) return guess_hi; + tm_hi = *tm; + + while (guess_lo + 1 < guess_hi) { /* there is a gap between lo and hi. */ + unsigned long range; + int a, b; + /* + Try precious guess by a linear interpolation at first. + `a' and `b' is a coefficient of guess_lo and guess_hi. + `range' is approximation of maximum error by the interpolation. + (a + b)**2 should be less than 2**31 to avoid overflow. + When these parameter is wrong, binary search is used. + */ + a = (tm_hi.tm_year - tptr->tm_year); + b = (tptr->tm_year - tm_lo.tm_year); + range = 366 * 24 * 3600; + if (a + b < 46000 / 366) { + /* 46000 is selected as `some big number less than sqrt(2**31)'. */ + /* The distinction between leap/non-leap year is not important here. */ + static int days[] = { + 0, + 0 + 31, + 0 + 31 + 29, + 0 + 31 + 29 + 31, + 0 + 31 + 29 + 31 + 30, + 0 + 31 + 29 + 31 + 30 + 31, + 0 + 31 + 29 + 31 + 30 + 31 + 30, + 0 + 31 + 29 + 31 + 30 + 31 + 30 + 31, + 0 + 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31, + 0 + 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30, + 0 + 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31, + 0 + 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 + /* Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov */ + }; + a *= 366; + b *= 366; + d = days[tptr->tm_mon] + tptr->tm_mday; + a += days[tm_hi.tm_mon] + tm_hi.tm_mday - d; + b += d - (days[tm_lo.tm_mon] + tm_lo.tm_mday); + range = 2 * 24 * 3600; + } + if (a + b <= 1) { + range = 2; + a *= 24 * 3600; + b *= 24 * 3600; + d = tptr->tm_hour * 3600 + tptr->tm_min * 60 + tptr->tm_sec; + a += tm_hi.tm_hour * 3600 + tm_hi.tm_min * 60 + tm_hi.tm_sec - d; + b += d - (tm_lo.tm_hour * 3600 + tm_lo.tm_min * 60 + tm_lo.tm_sec); + } + if (a <= 0) a = 1; + if (b <= 0) b = 1; + d = a + b; + guess = guess_lo / d * a + guess_hi / d * b; + /* Although `%' may not work with negative value, + it doesn't cause serious problem because there is a fail safe. */ + guess += ((guess_lo % d) * a + (guess_hi % d) * b) / d; + + fixguess: + if (guess <= guess_lo || guess >= guess_hi) { + /* Precious guess is invalid. try binary search. */ + guess = guess_lo / 2 + guess_hi / 2; + if (guess <= guess_lo) + guess = guess_lo + 1; + else if (guess >= guess_hi) + guess = guess_hi - 1; + range = 0; + } + + tm = (utc_p ? gmtime : localtime)(&guess); + if (!tm) goto error; + + d = tmcmp(tptr, tm); + if (d == 0) { + if (!utc_p && !tm->tm_isdst) { + /* When leaving DST, there may be two time corresponding to given + argument. make_time_t returns DST in such cases. */ + /* xxx this assumes a difference in time as 3600 seconds. */ + time_t guess2 = guess - 3600; + tm = localtime(&guess2); + if (!tm) return guess; + if (tmcmp(tptr, tm) == 0) + return guess2; } - if (lt.tm_isdst) guess += 3600; - guess += tzsec; -#ifndef NEGATIVE_TIME_T - if (guess < 0) goto out_of_range; -#endif - tm = localtime(&guess); - if (!tm) goto error; - if (lt.tm_isdst != tm->tm_isdst || tptr->tm_hour != tm->tm_hour) { - time_t tmp = guess - 3600; - tm = localtime(&tmp); - if (!tm) goto error; - if (tptr->tm_hour == tm->tm_hour) { - guess = tmp; - } - else if (lt.tm_isdst == tm->tm_isdst) { - tmp = guess + 3600; - tm = localtime(&tmp); - if (!tm) goto error; - if (tptr->tm_hour == tm->tm_hour) { - guess = tmp; - } - } + return guess; + } + else if (d < 0) { + guess_hi = guess; + tm_hi = *tm; + if (range && range < (unsigned long)(guess_hi - guess_lo)) { + guess = guess - range; + range = 0; + goto fixguess; } - if (tptr->tm_min != tm->tm_min) { - guess += (tptr->tm_min - tm->tm_min) * 60; + } + else { + guess_lo = guess; + tm_lo = *tm; + if (range && range < (unsigned long)(guess_hi - guess_lo)) { + guess = guess + range; + range = 0; + goto fixguess; } -#ifndef NEGATIVE_TIME_T - if (guess < 0) goto out_of_range; -#endif + } + } + /* given time is not found. */ + if (guess_lo + 1 == guess_hi) { + /* given argument is invalid: 04/29 at non-leap year for example. */ + return guess_hi; + } + else { + /* given argument is in a gap. When it enters DST, for example. */ + d = tptr->tm_sec - tm_lo.tm_sec; + d += (tptr->tm_min - tm_lo.tm_min) * 60; + d += (tptr->tm_hour - tm_lo.tm_hour) * 3600; + if (d < 0) + d += 24 * 3600; + return guess_hi + d - 1; } -#ifdef NEGATIVE_TIME_T - if (oguess > 365 * 24 * 3600 && guess < 0) goto out_of_range; - if (guess > 365 * 24 * 3600 && oguess < 0) goto out_of_range; -#endif - - return guess; out_of_range: rb_raise(rb_eArgError, "time out of range"); diff --git a/version.h b/version.h index 29813a6f6d..68660d0aa9 100644 --- a/version.h +++ b/version.h @@ -1,4 +1,4 @@ #define RUBY_VERSION "1.7.0" -#define RUBY_RELEASE_DATE "2001-05-22" +#define RUBY_RELEASE_DATE "2001-05-24" #define RUBY_VERSION_CODE 170 -#define RUBY_RELEASE_CODE 20010522 +#define RUBY_RELEASE_CODE 20010524 -- cgit v1.2.3