diff options
author | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2012-04-16 07:22:43 +0000 |
---|---|---|
committer | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2012-04-16 07:22:43 +0000 |
commit | f2979f3101a0cb1467971ea3b4794c19c6b639dd (patch) | |
tree | 3d71a8b25c869ac5fc69a59baae1711ce2e7db92 | |
parent | 72fffe5cee069d9f47a7a8dc808885aec67da225 (diff) | |
download | ruby-f2979f3101a0cb1467971ea3b4794c19c6b639dd.tar.gz |
* win32/win32.c (gmtime_r, localtime_r): POSIX compliant reentrant
versions.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@35348 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r-- | ChangeLog | 5 | ||||
-rw-r--r-- | configure.in | 1 | ||||
-rw-r--r-- | include/ruby/win32.h | 3 | ||||
-rw-r--r-- | win32/Makefile.sub | 1 | ||||
-rw-r--r-- | win32/win32.c | 105 |
5 files changed, 114 insertions, 1 deletions
@@ -1,4 +1,7 @@ -Mon Apr 16 16:08:18 2012 Nobuyoshi Nakada <nobu@ruby-lang.org> +Mon Apr 16 16:22:40 2012 Nobuyoshi Nakada <nobu@ruby-lang.org> + + * win32/win32.c (gmtime_r, localtime_r): POSIX compliant reentrant + versions. * configure.in (RUBY_MSVCRT_VERSION): define on mingw too. diff --git a/configure.in b/configure.in index f7e6f3cd95..0dd9203792 100644 --- a/configure.in +++ b/configure.in @@ -1089,6 +1089,7 @@ main() rb_cv_negative_time_t=no ac_cv_func_fcntl=yes ac_cv_func_flock=yes + ac_cv_func_gmtime_r=yes rb_cv_large_fd_select=yes AC_LIBOBJ([langinfo]) : ${enable_win95=maybe} diff --git a/include/ruby/win32.h b/include/ruby/win32.h index 302bf5e8cf..1f966484b8 100644 --- a/include/ruby/win32.h +++ b/include/ruby/win32.h @@ -690,6 +690,9 @@ struct tms { int rb_w32_times(struct tms *); +struct tm *gmtime_r(const time_t *, struct tm *); +struct tm *localtime_r(const time_t *, struct tm *); + /* thread stuff */ int rb_w32_sleep(unsigned long msec); int rb_w32_putc(int, FILE*); diff --git a/win32/Makefile.sub b/win32/Makefile.sub index 33ea9835d1..10bb4003e0 100644 --- a/win32/Makefile.sub +++ b/win32/Makefile.sub @@ -651,6 +651,7 @@ $(CONFIG_H): $(MKFILES) $(srcdir)/win32/Makefile.sub $(win_srcdir)/Makefile.sub #define HAVE_SIGNBIT 1 #define HAVE_TZNAME 1 #define HAVE_DAYLIGHT 1 +#define HAVE_GMTIME_R 1 #define SETPGRP_VOID 1 #define RSHIFT(x,y) ((x)>>(int)y) #define HAVE_RB_FD_INIT 1 diff --git a/win32/win32.c b/win32/win32.c index c114aa7660..687d8bd04a 100644 --- a/win32/win32.c +++ b/win32/win32.c @@ -6257,3 +6257,108 @@ char rb_w32_fd_is_text(int fd) { return _osfile(fd) & FTEXT; } + +#if RUBY_MSVCRT_VERSION < 80 +static int +unixtime_to_systemtime(const time_t t, SYSTEMTIME *st) +{ + FILETIME ft; + if (unixtime_to_filetime(t, &ft)) return -1; + if (!FileTimeToSystemTime(&ft, st)) return -1; + return 0; +} + +static void +systemtime_to_tm(const SYSTEMTIME *st, struct tm *t) +{ + int y = st->wYear, m = st->wMonth, d = st->wDay; + t->tm_sec = st->wSecond; + t->tm_min = st->wMinute; + t->tm_hour = st->wHour; + t->tm_mday = st->wDay; + t->tm_mon = st->wMonth - 1; + t->tm_year = y - 1900; + t->tm_wday = st->wDayOfWeek; + switch (m) { + case 1: + break; + case 2: + d += 31; + break; + default: + d += 31 + 28 + (!(y % 4) && ((y % 100) || !(y % 400))); + d += ((m - 3) * 153 + 2) / 5; + break; + } + t->tm_yday = d - 1; +} + +static int +systemtime_to_localtime(TIME_ZONE_INFORMATION *tz, SYSTEMTIME *gst, SYSTEMTIME *lst) +{ + TIME_ZONE_INFORMATION stdtz; + SYSTEMTIME sst; + + if (!SystemTimeToTzSpecificLocalTime(tz, gst, lst)) return -1; + if (!tz) { + GetTimeZoneInformation(&stdtz); + tz = &stdtz; + } + if (tz->StandardBias == tz->DaylightBias) return 0; + if (!tz->StandardDate.wMonth) return 0; + if (!tz->DaylightDate.wMonth) return 0; + if (tz != &stdtz) stdtz = *tz; + + stdtz.StandardDate.wMonth = stdtz.DaylightDate.wMonth = 0; + if (!SystemTimeToTzSpecificLocalTime(&stdtz, gst, &sst)) return 0; + if (lst->wMinute == sst.wMinute && lst->wHour == sst.wHour) + return 0; + return 1; +} +#endif + +struct tm * +gmtime_r(const time_t *tp, struct tm *rp) +{ + int e = EINVAL; + if (!tp || !rp) { + error: + errno = e; + return NULL; + } +#if RUBY_MSVCRT_VERSION >= 80 + e = gmtime_s(rp, tp); + if (e != 0) goto error; +#else + { + SYSTEMTIME st; + if (unixtime_to_systemtime(*tp, &st)) goto error; + rp->tm_isdst = 0; + systemtime_to_tm(&st, rp); + } +#endif + return rp; +} + +struct tm * +localtime_r(const time_t *tp, struct tm *rp) +{ + int e = EINVAL; + if (!tp || !rp) { + error: + errno = e; + return NULL; + } +#if RUBY_MSVCRT_VERSION >= 80 + e = localtime_s(rp, tp); + if (e) goto error; +#else + { + SYSTEMTIME gst, lst; + if (unixtime_to_systemtime(*tp, &gst)) goto error; + rp->tm_isdst = systemtime_to_localtime(NULL, &gst, &lst); + systemtime_to_tm(&lst, rp); + } +#endif + return rp; +} |