From 4426390a5531e6b3e66e581d1911b9239333fa33 Mon Sep 17 00:00:00 2001 From: Freddie Chopin Date: Sat, 6 Sep 2014 00:00:12 +0200 Subject: [PATCH] libc/time: Remove dependency of gmtime() on time zone related code 1. Move mon_lengths array to new file, rename to __month_lengths 2. Move __tzcalc_limits() to new file 3. Move time zone related part of _mktm_r() to localtime_r(), before performing these time zone adjustments call gmtime_r() 4. Move remaining part of _mktm_r() to gmtime_r() 5. Remove mktm_r.c 6. Modify Makefile.am and regenerate Makefile.in --- newlib/libc/time/Makefile.am | 3 +- newlib/libc/time/Makefile.in | 30 +++-- newlib/libc/time/gmtime_r.c | 97 +++++++++++++- newlib/libc/time/lcltime_r.c | 112 +++++++++++++++- newlib/libc/time/local.h | 3 +- newlib/libc/time/mktm_r.c | 277 --------------------------------------- newlib/libc/time/month_lengths.c | 14 ++ newlib/libc/time/tzcalc_limits.c | 77 +++++++++++ 8 files changed, 319 insertions(+), 294 deletions(-) delete mode 100644 newlib/libc/time/mktm_r.c create mode 100644 newlib/libc/time/month_lengths.c create mode 100644 newlib/libc/time/tzcalc_limits.c diff --git a/newlib/libc/time/Makefile.am b/newlib/libc/time/Makefile.am index 9571631..95f088a 100644 --- a/newlib/libc/time/Makefile.am +++ b/newlib/libc/time/Makefile.am @@ -17,10 +17,11 @@ LIB_SOURCES = \ lcltime.c \ lcltime_r.c \ mktime.c \ - mktm_r.c \ + month_lengths.c \ strftime.c \ strptime.c \ time.c \ + tzcalc_limits.c \ tzlock.c \ tzset.c \ tzset_r.c \ diff --git a/newlib/libc/time/Makefile.in b/newlib/libc/time/Makefile.in index c28caaf..48ba064 100644 --- a/newlib/libc/time/Makefile.in +++ b/newlib/libc/time/Makefile.in @@ -78,19 +78,20 @@ am__objects_1 = lib_a-asctime.$(OBJEXT) lib_a-asctime_r.$(OBJEXT) \ lib_a-gettzinfo.$(OBJEXT) lib_a-gmtime.$(OBJEXT) \ lib_a-gmtime_r.$(OBJEXT) lib_a-lcltime.$(OBJEXT) \ lib_a-lcltime_r.$(OBJEXT) lib_a-mktime.$(OBJEXT) \ - lib_a-mktm_r.$(OBJEXT) lib_a-strftime.$(OBJEXT) \ + lib_a-month_lengths.$(OBJEXT) lib_a-strftime.$(OBJEXT) \ lib_a-strptime.$(OBJEXT) lib_a-time.$(OBJEXT) \ - lib_a-tzlock.$(OBJEXT) lib_a-tzset.$(OBJEXT) \ - lib_a-tzset_r.$(OBJEXT) lib_a-tzvars.$(OBJEXT) \ - lib_a-wcsftime.$(OBJEXT) + lib_a-tzcalc_limits.$(OBJEXT) lib_a-tzlock.$(OBJEXT) \ + lib_a-tzset.$(OBJEXT) lib_a-tzset_r.$(OBJEXT) \ + lib_a-tzvars.$(OBJEXT) lib_a-wcsftime.$(OBJEXT) @USE_LIBTOOL_FALSE@am_lib_a_OBJECTS = $(am__objects_1) lib_a_OBJECTS = $(am_lib_a_OBJECTS) LTLIBRARIES = $(noinst_LTLIBRARIES) libtime_la_LIBADD = am__objects_2 = asctime.lo asctime_r.lo clock.lo ctime.lo ctime_r.lo \ difftime.lo gettzinfo.lo gmtime.lo gmtime_r.lo lcltime.lo \ - lcltime_r.lo mktime.lo mktm_r.lo strftime.lo strptime.lo \ - time.lo tzlock.lo tzset.lo tzset_r.lo tzvars.lo wcsftime.lo + lcltime_r.lo mktime.lo month_lengths.lo strftime.lo \ + strptime.lo time.lo tzcalc_limits.lo tzlock.lo tzset.lo \ + tzset_r.lo tzvars.lo wcsftime.lo @USE_LIBTOOL_TRUE@am_libtime_la_OBJECTS = $(am__objects_2) libtime_la_OBJECTS = $(am_libtime_la_OBJECTS) libtime_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ @@ -277,10 +278,11 @@ LIB_SOURCES = \ lcltime.c \ lcltime_r.c \ mktime.c \ - mktm_r.c \ + month_lengths.c \ strftime.c \ strptime.c \ time.c \ + tzcalc_limits.c \ tzlock.c \ tzset.c \ tzset_r.c \ @@ -454,11 +456,11 @@ lib_a-mktime.o: mktime.c lib_a-mktime.obj: mktime.c $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-mktime.obj `if test -f 'mktime.c'; then $(CYGPATH_W) 'mktime.c'; else $(CYGPATH_W) '$(srcdir)/mktime.c'; fi` -lib_a-mktm_r.o: mktm_r.c - $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-mktm_r.o `test -f 'mktm_r.c' || echo '$(srcdir)/'`mktm_r.c +lib_a-month_lengths.o: month_lengths.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-month_lengths.o `test -f 'month_lengths.c' || echo '$(srcdir)/'`month_lengths.c -lib_a-mktm_r.obj: mktm_r.c - $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-mktm_r.obj `if test -f 'mktm_r.c'; then $(CYGPATH_W) 'mktm_r.c'; else $(CYGPATH_W) '$(srcdir)/mktm_r.c'; fi` +lib_a-month_lengths.obj: month_lengths.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-month_lengths.obj `if test -f 'month_lengths.c'; then $(CYGPATH_W) 'month_lengths.c'; else $(CYGPATH_W) '$(srcdir)/month_lengths.c'; fi` lib_a-strftime.o: strftime.c $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-strftime.o `test -f 'strftime.c' || echo '$(srcdir)/'`strftime.c @@ -478,6 +480,12 @@ lib_a-time.o: time.c lib_a-time.obj: time.c $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-time.obj `if test -f 'time.c'; then $(CYGPATH_W) 'time.c'; else $(CYGPATH_W) '$(srcdir)/time.c'; fi` +lib_a-tzcalc_limits.o: tzcalc_limits.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-tzcalc_limits.o `test -f 'tzcalc_limits.c' || echo '$(srcdir)/'`tzcalc_limits.c + +lib_a-tzcalc_limits.obj: tzcalc_limits.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-tzcalc_limits.obj `if test -f 'tzcalc_limits.c'; then $(CYGPATH_W) 'tzcalc_limits.c'; else $(CYGPATH_W) '$(srcdir)/tzcalc_limits.c'; fi` + lib_a-tzlock.o: tzlock.c $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-tzlock.o `test -f 'tzlock.c' || echo '$(srcdir)/'`tzlock.c diff --git a/newlib/libc/time/gmtime_r.c b/newlib/libc/time/gmtime_r.c index 14c9c76..1111cbc 100644 --- a/newlib/libc/time/gmtime_r.c +++ b/newlib/libc/time/gmtime_r.c @@ -1,14 +1,107 @@ /* * gmtime_r.c + * Original Author: Adapted from tzcode maintained by Arthur David Olson. + * Modifications: + * - Changed to mktm_r and added __tzcalc_limits - 04/10/02, Jeff Johnston + * - Fixed bug in mday computations - 08/12/04, Alex Mogilnikov + * - Fixed bug in __tzcalc_limits - 08/12/04, Alex Mogilnikov + * - Move code from _mktm_r() to gmtime_r() - 05/09/14, Freddie Chopin + * + * Converts the calendar time pointed to by tim_p into a broken-down time + * expressed as local time. Returns a pointer to a structure containing the + * broken-down time. */ -#include #include "local.h" +/* there are 97 leap years in 400-year periods */ +#define DAYS_PER_400_YEARS ((400 - 97) * 365 + 97 * 366) +/* there are 24 leap years in 100-year periods */ +#define DAYS_PER_100_YEARS ((100 - 24) * 365 + 24 * 366) +/* there is one leap year every 4 years */ +#define DAYS_PER_4_YEARS (3 * 365 + 366) + +static _CONST int days_per_year[4] = { + 365, /* 1970 or 1966 */ + 365, /* 1971 or 1967 */ + 366, /* 1972 or 1968 */ + 365 /* 1973 or 1969 */ +} ; + struct tm * _DEFUN (gmtime_r, (tim_p, res), _CONST time_t *__restrict tim_p _AND struct tm *__restrict res) { - return (_mktm_r (tim_p, res, 1)); + long days, rem; + _CONST time_t lcltime = *tim_p; + int year; + int years400, years100, years4; + int yearleap; + _CONST int *ip; + + days = ((long)lcltime) / SECSPERDAY; + rem = ((long)lcltime) % SECSPERDAY; + while (rem < 0) + { + rem += SECSPERDAY; + --days; + } + while (rem >= SECSPERDAY) + { + rem -= SECSPERDAY; + ++days; + } + + /* compute hour, min, and sec */ + res->tm_hour = (int) (rem / SECSPERHOUR); + rem %= SECSPERHOUR; + res->tm_min = (int) (rem / SECSPERMIN); + res->tm_sec = (int) (rem % SECSPERMIN); + + /* compute day of week */ + if ((res->tm_wday = ((EPOCH_WDAY + days) % DAYSPERWEEK)) < 0) + res->tm_wday += DAYSPERWEEK; + + /* compute year & day of year */ + years400 = days / DAYS_PER_400_YEARS; + days -= years400 * DAYS_PER_400_YEARS; + years100 = days / DAYS_PER_100_YEARS; + days -= years100 * DAYS_PER_100_YEARS; + years4 = days / DAYS_PER_4_YEARS; + days -= years4 * DAYS_PER_4_YEARS; + + year = EPOCH_YEAR + years400 * 400 + years100 * 100 + years4 * 4; + + /* the value left in days is based in 1970 */ + if (days < 0) + { + ip = &days_per_year[3]; + while (days < 0) + { + days += *ip--; + --year; + } + } + else + { + ip = &days_per_year[0]; + while (days >= *ip) + { + days -= *ip++; + ++year; + } + } + + res->tm_year = year - YEAR_BASE; + res->tm_yday = days; + yearleap = isleap(year); + ip = __month_lengths[yearleap]; + for (res->tm_mon = 0; days >= ip[res->tm_mon]; ++res->tm_mon) + days -= ip[res->tm_mon]; + res->tm_mday = days + 1; + + res->tm_isdst = 0; + + return (res); } diff --git a/newlib/libc/time/lcltime_r.c b/newlib/libc/time/lcltime_r.c index 9e168aa..9094e5d 100644 --- a/newlib/libc/time/lcltime_r.c +++ b/newlib/libc/time/lcltime_r.c @@ -1,12 +1,18 @@ /* * localtime_r.c + * Original Author: Adapted from tzcode maintained by Arthur David Olson. + * Modifications: + * - Changed to mktm_r and added __tzcalc_limits - 04/10/02, Jeff Johnston + * - Fixed bug in mday computations - 08/12/04, Alex Mogilnikov + * - Fixed bug in __tzcalc_limits - 08/12/04, Alex Mogilnikov + * - Implement localtime_r() with gmtime_r() and the conditional code moved + * from _mktm_r() - 05/09/14, Freddie Chopin * * Converts the calendar time pointed to by tim_p into a broken-down time * expressed as local time. Returns a pointer to a structure containing the * broken-down time. */ -#include #include "local.h" struct tm * @@ -14,5 +20,107 @@ _DEFUN (localtime_r, (tim_p, res), _CONST time_t *__restrict tim_p _AND struct tm *__restrict res) { - return _mktm_r (tim_p, res, 0); + long offset; + int hours, mins, secs; + int year; + __tzinfo_type *_CONST tz = __gettzinfo (); + _CONST int *ip; + + res = gmtime_r (tim_p, res); + + year = res->tm_year + YEAR_BASE; + ip = __month_lengths[isleap(year)]; + + TZ_LOCK; + if (_daylight) + { + if (year == tz->__tzyear || __tzcalc_limits (year)) + res->tm_isdst = (tz->__tznorth + ? (*tim_p >= tz->__tzrule[0].change + && *tim_p < tz->__tzrule[1].change) + : (*tim_p >= tz->__tzrule[0].change + || *tim_p < tz->__tzrule[1].change)); + else + res->tm_isdst = -1; + } + else + res->tm_isdst = 0; + + offset = (res->tm_isdst == 1 + ? tz->__tzrule[1].offset + : tz->__tzrule[0].offset); + + hours = (int) (offset / SECSPERHOUR); + offset = offset % SECSPERHOUR; + + mins = (int) (offset / SECSPERMIN); + secs = (int) (offset % SECSPERMIN); + + res->tm_sec -= secs; + res->tm_min -= mins; + res->tm_hour -= hours; + + if (res->tm_sec >= SECSPERMIN) + { + res->tm_min += 1; + res->tm_sec -= SECSPERMIN; + } + else if (res->tm_sec < 0) + { + res->tm_min -= 1; + res->tm_sec += SECSPERMIN; + } + if (res->tm_min >= MINSPERHOUR) + { + res->tm_hour += 1; + res->tm_min -= MINSPERHOUR; + } + else if (res->tm_min < 0) + { + res->tm_hour -= 1; + res->tm_min += MINSPERHOUR; + } + if (res->tm_hour >= HOURSPERDAY) + { + ++res->tm_yday; + ++res->tm_wday; + if (res->tm_wday > 6) + res->tm_wday = 0; + ++res->tm_mday; + res->tm_hour -= HOURSPERDAY; + if (res->tm_mday > ip[res->tm_mon]) + { + res->tm_mday -= ip[res->tm_mon]; + res->tm_mon += 1; + if (res->tm_mon == 12) + { + res->tm_mon = 0; + res->tm_year += 1; + res->tm_yday = 0; + } + } + } + else if (res->tm_hour < 0) + { + res->tm_yday -= 1; + res->tm_wday -= 1; + if (res->tm_wday < 0) + res->tm_wday = 6; + res->tm_mday -= 1; + res->tm_hour += 24; + if (res->tm_mday == 0) + { + res->tm_mon -= 1; + if (res->tm_mon < 0) + { + res->tm_mon = 11; + res->tm_year -= 1; + res->tm_yday = 364 + isleap(res->tm_year + YEAR_BASE); + } + res->tm_mday = ip[res->tm_mon]; + } + } + TZ_UNLOCK; + + return (res); } diff --git a/newlib/libc/time/local.h b/newlib/libc/time/local.h index 9d9ef87..5fc3ddc 100644 --- a/newlib/libc/time/local.h +++ b/newlib/libc/time/local.h @@ -19,9 +19,10 @@ #define isleap(y) ((((y) % 4) == 0 && ((y) % 100) != 0) || ((y) % 400) == 0) -struct tm * _EXFUN (_mktm_r, (_CONST time_t *, struct tm *, int __is_gmtime)); int _EXFUN (__tzcalc_limits, (int __year)); +extern _CONST int __month_lengths[2][MONSPERYEAR]; + /* locks for multi-threading */ #ifdef __SINGLE_THREAD__ #define TZ_LOCK diff --git a/newlib/libc/time/mktm_r.c b/newlib/libc/time/mktm_r.c deleted file mode 100644 index 2668efd..0000000 --- a/newlib/libc/time/mktm_r.c +++ /dev/null @@ -1,277 +0,0 @@ -/* - * mktm_r.c - * Original Author: Adapted from tzcode maintained by Arthur David Olson. - * Modifications: Changed to mktm_r and added __tzcalc_limits - 04/10/02, Jeff Johnston - * Fixed bug in mday computations - 08/12/04, Alex Mogilnikov - * Fixed bug in __tzcalc_limits - 08/12/04, Alex Mogilnikov - * - * Converts the calendar time pointed to by tim_p into a broken-down time - * expressed as local time. Returns a pointer to a structure containing the - * broken-down time. - */ - -#include -#include -#include "local.h" - -/* there are 97 leap years in 400-year periods */ -#define DAYS_PER_400_YEARS ((400 - 97) * 365 + 97 * 366) -/* there are 24 leap years in 100-year periods */ -#define DAYS_PER_100_YEARS ((100 - 24) * 365 + 24 * 366) -/* there is one leap year every 4 years */ -#define DAYS_PER_4_YEARS (3 * 365 + 366) - -static _CONST int mon_lengths[2][MONSPERYEAR] = { - {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, - {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} -} ; - -static _CONST int days_per_year[4] = { - 365, /* 1970 or 1966 */ - 365, /* 1971 or 1967 */ - 366, /* 1972 or 1968 */ - 365 /* 1973 or 1969 */ -} ; - -struct tm * -_DEFUN (_mktm_r, (tim_p, res, is_gmtime), - _CONST time_t * tim_p _AND - struct tm *res _AND - int is_gmtime) -{ - long days, rem; - time_t lcltime; - int y; - int years400, years100, years4; - int yleap; - _CONST int *ip; - __tzinfo_type *tz = __gettzinfo (); - - /* base decision about std/dst time on current time */ - lcltime = *tim_p; - - days = ((long)lcltime) / SECSPERDAY; - rem = ((long)lcltime) % SECSPERDAY; - while (rem < 0) - { - rem += SECSPERDAY; - --days; - } - while (rem >= SECSPERDAY) - { - rem -= SECSPERDAY; - ++days; - } - - /* compute hour, min, and sec */ - res->tm_hour = (int) (rem / SECSPERHOUR); - rem %= SECSPERHOUR; - res->tm_min = (int) (rem / SECSPERMIN); - res->tm_sec = (int) (rem % SECSPERMIN); - - /* compute day of week */ - if ((res->tm_wday = ((EPOCH_WDAY + days) % DAYSPERWEEK)) < 0) - res->tm_wday += DAYSPERWEEK; - - /* compute year & day of year */ - years400 = days / DAYS_PER_400_YEARS; - days -= years400 * DAYS_PER_400_YEARS; - years100 = days / DAYS_PER_100_YEARS; - days -= years100 * DAYS_PER_100_YEARS; - years4 = days / DAYS_PER_4_YEARS; - days -= years4 * DAYS_PER_4_YEARS; - - y = EPOCH_YEAR + years400 * 400 + years100 * 100 + years4 * 4; - - /* the value left in days is based in 1970 */ - if (days < 0) - { - ip = &days_per_year[3]; - while (days < 0) - { - days += *ip--; - --y; - } - } - else - { - ip = &days_per_year[0]; - while (days >= *ip) - { - days -= *ip++; - ++y; - } - } - - res->tm_year = y - YEAR_BASE; - res->tm_yday = days; - yleap = isleap(y); - ip = mon_lengths[yleap]; - for (res->tm_mon = 0; days >= ip[res->tm_mon]; ++res->tm_mon) - days -= ip[res->tm_mon]; - res->tm_mday = days + 1; - - if (!is_gmtime) - { - long offset; - int hours, mins, secs; - - TZ_LOCK; - if (_daylight) - { - if (y == tz->__tzyear || __tzcalc_limits (y)) - res->tm_isdst = (tz->__tznorth - ? (*tim_p >= tz->__tzrule[0].change - && *tim_p < tz->__tzrule[1].change) - : (*tim_p >= tz->__tzrule[0].change - || *tim_p < tz->__tzrule[1].change)); - else - res->tm_isdst = -1; - } - else - res->tm_isdst = 0; - - offset = (res->tm_isdst == 1 - ? tz->__tzrule[1].offset - : tz->__tzrule[0].offset); - - hours = (int) (offset / SECSPERHOUR); - offset = offset % SECSPERHOUR; - - mins = (int) (offset / SECSPERMIN); - secs = (int) (offset % SECSPERMIN); - - res->tm_sec -= secs; - res->tm_min -= mins; - res->tm_hour -= hours; - - if (res->tm_sec >= SECSPERMIN) - { - res->tm_min += 1; - res->tm_sec -= SECSPERMIN; - } - else if (res->tm_sec < 0) - { - res->tm_min -= 1; - res->tm_sec += SECSPERMIN; - } - if (res->tm_min >= MINSPERHOUR) - { - res->tm_hour += 1; - res->tm_min -= MINSPERHOUR; - } - else if (res->tm_min < 0) - { - res->tm_hour -= 1; - res->tm_min += MINSPERHOUR; - } - if (res->tm_hour >= HOURSPERDAY) - { - ++res->tm_yday; - ++res->tm_wday; - if (res->tm_wday > 6) - res->tm_wday = 0; - ++res->tm_mday; - res->tm_hour -= HOURSPERDAY; - if (res->tm_mday > ip[res->tm_mon]) - { - res->tm_mday -= ip[res->tm_mon]; - res->tm_mon += 1; - if (res->tm_mon == 12) - { - res->tm_mon = 0; - res->tm_year += 1; - res->tm_yday = 0; - } - } - } - else if (res->tm_hour < 0) - { - res->tm_yday -= 1; - res->tm_wday -= 1; - if (res->tm_wday < 0) - res->tm_wday = 6; - res->tm_mday -= 1; - res->tm_hour += 24; - if (res->tm_mday == 0) - { - res->tm_mon -= 1; - if (res->tm_mon < 0) - { - res->tm_mon = 11; - res->tm_year -= 1; - res->tm_yday = 364 + isleap(res->tm_year + 1900); - } - res->tm_mday = ip[res->tm_mon]; - } - } - TZ_UNLOCK; - } - else - res->tm_isdst = 0; - - return (res); -} - -int -_DEFUN (__tzcalc_limits, (year), - int year) -{ - int days, year_days, years; - int i, j; - __tzinfo_type *tz = __gettzinfo (); - - if (year < EPOCH_YEAR) - return 0; - - tz->__tzyear = year; - - years = (year - EPOCH_YEAR); - - year_days = years * 365 + - (years - 1 + EPOCH_YEARS_SINCE_LEAP) / 4 - (years - 1 + EPOCH_YEARS_SINCE_CENTURY) / 100 + - (years - 1 + EPOCH_YEARS_SINCE_LEAP_CENTURY) / 400; - - for (i = 0; i < 2; ++i) - { - if (tz->__tzrule[i].ch == 'J') { - /* The Julian day n (1 <= n <= 365). */ - days = year_days + tz->__tzrule[i].d + - (isleap(year) && tz->__tzrule[i].d >= 60); - /* Convert to yday */ - --days; - } else if (tz->__tzrule[i].ch == 'D') - days = year_days + tz->__tzrule[i].d; - else - { - int yleap = isleap(year); - int m_day, m_wday, wday_diff; - _CONST int *ip = mon_lengths[yleap]; - - days = year_days; - - for (j = 1; j < tz->__tzrule[i].m; ++j) - days += ip[j-1]; - - m_wday = (EPOCH_WDAY + days) % DAYSPERWEEK; - - wday_diff = tz->__tzrule[i].d - m_wday; - if (wday_diff < 0) - wday_diff += DAYSPERWEEK; - m_day = (tz->__tzrule[i].n - 1) * DAYSPERWEEK + wday_diff; - - while (m_day >= ip[j-1]) - m_day -= DAYSPERWEEK; - - days += m_day; - } - - /* store the change-over time in GMT form by adding offset */ - tz->__tzrule[i].change = days * SECSPERDAY + - tz->__tzrule[i].s + tz->__tzrule[i].offset; - } - - tz->__tznorth = (tz->__tzrule[0].change < tz->__tzrule[1].change); - - return 1; -} diff --git a/newlib/libc/time/month_lengths.c b/newlib/libc/time/month_lengths.c new file mode 100644 index 0000000..2871802 --- /dev/null +++ b/newlib/libc/time/month_lengths.c @@ -0,0 +1,14 @@ +/* + * month_lengths.c + * + * Array __month_lengths[] is (indirectly) needed by tzset(), mktime(), + * gmtime() and localtime(). To break any dependencies, this array is moved to + * separate source file. + */ + +#include "local.h" + +_CONST int __month_lengths[2][MONSPERYEAR] = { + {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, + {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} +} ; diff --git a/newlib/libc/time/tzcalc_limits.c b/newlib/libc/time/tzcalc_limits.c new file mode 100644 index 0000000..8a0bda3 --- /dev/null +++ b/newlib/libc/time/tzcalc_limits.c @@ -0,0 +1,77 @@ +/* + * tzcalc_limits.c + * Original Author: Adapted from tzcode maintained by Arthur David Olson. + * Modifications: + * - Changed to mktm_r and added __tzcalc_limits - 04/10/02, Jeff Johnston + * - Fixed bug in mday computations - 08/12/04, Alex Mogilnikov + * - Fixed bug in __tzcalc_limits - 08/12/04, Alex Mogilnikov + * - Moved __tzcalc_limits() to separate file - 05/09/14, Freddie Chopin + */ + +#include "local.h" + +int +_DEFUN (__tzcalc_limits, (year), + int year) +{ + int days, year_days, years; + int i, j; + __tzinfo_type *_CONST tz = __gettzinfo (); + + if (year < EPOCH_YEAR) + return 0; + + tz->__tzyear = year; + + years = (year - EPOCH_YEAR); + + year_days = years * 365 + + (years - 1 + EPOCH_YEARS_SINCE_LEAP) / 4 - + (years - 1 + EPOCH_YEARS_SINCE_CENTURY) / 100 + + (years - 1 + EPOCH_YEARS_SINCE_LEAP_CENTURY) / 400; + + for (i = 0; i < 2; ++i) + { + if (tz->__tzrule[i].ch == 'J') + { + /* The Julian day n (1 <= n <= 365). */ + days = year_days + tz->__tzrule[i].d + + (isleap(year) && tz->__tzrule[i].d >= 60); + /* Convert to yday */ + --days; + } + else if (tz->__tzrule[i].ch == 'D') + days = year_days + tz->__tzrule[i].d; + else + { + _CONST int yleap = isleap(year); + int m_day, m_wday, wday_diff; + _CONST int *_CONST ip = __month_lengths[yleap]; + + days = year_days; + + for (j = 1; j < tz->__tzrule[i].m; ++j) + days += ip[j-1]; + + m_wday = (EPOCH_WDAY + days) % DAYSPERWEEK; + + wday_diff = tz->__tzrule[i].d - m_wday; + if (wday_diff < 0) + wday_diff += DAYSPERWEEK; + m_day = (tz->__tzrule[i].n - 1) * DAYSPERWEEK + wday_diff; + + while (m_day >= ip[j-1]) + m_day -= DAYSPERWEEK; + + days += m_day; + } + + /* store the change-over time in GMT form by adding offset */ + tz->__tzrule[i].change = days * SECSPERDAY + + tz->__tzrule[i].s + tz->__tzrule[i].offset; + } + + tz->__tznorth = (tz->__tzrule[0].change < tz->__tzrule[1].change); + + return 1; +} -- 1.8.1.msysgit.1