[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
Fri Sep 5 22:19:00 GMT 2014


Hello!

Modified patch (with ChangeLog entry) attached.

This time I have gone a bit further, the summary of changes is contained 
in the patch, but I'm pasting it here for clarity:

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

The gain when using gmtime() only is the same as previously. It is also 
worth noting that with this change (just as with the previous version) 
if you have BOTH gmtime() and localtime() calls in your code it will be 
a bit bigger than before - about 150B of .text (on ARM Cortex-M3) - this 
is because now the code is spread between two functions, with a little 
bit of duplication of initializations, while previously it was only one 
function, so the compiler was able to optimize and reuse variables.

I hope that this time I did that right (;

Regards,
FCh
-------------- next part --------------
>From 5ac8f482a2700fd079baff56bb139e0982f9aed3 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..b6443dc 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..afbdefd 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..b3e0923 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..c0e0a96 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..070ca04 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..764e700
--- /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..31dda38
--- /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

-------------- next part --------------
2014-09-06  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.


More information about the Newlib mailing list