[PATCH] libc/time/gmtime_r.c, libc/time/lcltime_r.c,, libc/time/local.h, libc/time/mktm_r.c: move localtime related functionality, from _mktm_r() to new _mklocaltm_r() to break dependency of gmtime() on, timezones

Freddie Chopin freddie_chopin@op.pl
Thu Sep 11 20:18:00 GMT 2014


W dniu 2014-09-11 21:51, Jeff Johnston pisze:
> Hi Freddie,
>
> Corinna who was looking at this previously is on vacation so I am reviewing it.

Good to know, thanks for your review!

> The only comments I have are:
>
> 1. month_lengths needs to be renamed to be __month_lengths because it is now externalized.
> 2. you might as well be consistent with other files in LIB_SOURCES list of Makefile.am with regards to tabs vs spaces.

Both issues fixed. Updated patch and updated changelog attached.

Regards,
FCh
-------------- next part --------------
2014-09-11  Freddie Chopin  <freddie_chopin@op.pl>

	* libc\time\month_lengths.c: New file with __month_lengths array
	(previously mon_lengths array in mktm_r.c)
	* libc\time\tzcalc_limits.c: New file with __tzcalc_limits() from
	mktm_r.c
	* libc\time\lcltime_r.c (localtime_r): Simplify by changing call to
	_mktm_r() with call to gmtime_r() and code moved from _mktm_r() which
	was used to do time zone adjustments
	* libc\time\gmtime_r.c (gmtime_r): Simplify by moving all relevant
	code from _mktm_r(), breaking all dependencies on time zone related
	functions
	* libc\time\mktm_r.c: Delete file
	* libc\time\local.h: Update accordingly - remove declaration of
	_mktm_r(), add declaration of __month_lengths[]
	* libc\time\Makefile.am: Modify accordingly.
	* libc\time\Makefile.in: Regenerate.
-------------- next part --------------
From 4426390a5531e6b3e66e581d1911b9239333fa33 Mon Sep 17 00:00:00 2001
From: Freddie Chopin <freddie.chopin@gmail.com>
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 <alx@intellectronika.ru>
+ * - Fixed bug in __tzcalc_limits - 08/12/04, Alex Mogilnikov <alx@intellectronika.ru>
+ * - Move code from _mktm_r() to gmtime_r() - 05/09/14, Freddie Chopin <freddie_chopin@op.pl>
+ *
+ * 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 <time.h>
 #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 <alx@intellectronika.ru>
+ * - Fixed bug in __tzcalc_limits - 08/12/04, Alex Mogilnikov <alx@intellectronika.ru>
+ * - Implement localtime_r() with gmtime_r() and the conditional code moved
+ *   from _mktm_r() - 05/09/14, Freddie Chopin <freddie_chopin@op.pl>
  *
  * 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 <time.h>
 #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 <alx@intellectronika.ru>
- *                      Fixed bug in __tzcalc_limits - 08/12/04, Alex Mogilnikov <alx@intellectronika.ru>
- *
- * 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 <stdlib.h>
-#include <time.h>
-#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 <alx@intellectronika.ru>
+ * - Fixed bug in __tzcalc_limits - 08/12/04, Alex Mogilnikov <alx@intellectronika.ru>
+ * - Moved __tzcalc_limits() to separate file - 05/09/14, Freddie Chopin <freddie_chopin@op.pl>
+ */
+
+#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



More information about the Newlib mailing list