[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
Wed Sep 3 19:59:00 GMT 2014
Hello again (;
I attach patch and a ChangeLog entry with a bigger change to
time-related sources.
Currently functions gmtime() and localtime() are both implemented with
common code in _mktm_r(), which decides whether to do time zone
adjustments by additional parameter - is_gmtime, true for gmtime() and
false for localtime(). This way if you use gmtime() and don't care about
time zones, you get them anyway in the final binary.
This change moves all time zone related stuff from _mktm_r() to new
function _mklocaltm_r(). gmtime_r() still calls _mktm_r() (but with this
boolean parameter removed), while localtime_r() first calls _mktm_r()
and then calls _mklocaltm_r() using the result of _mktm_r().
This way you get time zone stuff in the final link only if it's really
needed - when you use localtime(). If you use just gmtime(), the time
zone functions are not linked, which saves about 1kB of flash and a
little below 100B of RAM (on ARM Cortex-M3). (the savings would be
bigger if proper locks are implemented - by default only stubs are used
and no code for mutexes is needed)
Actually the names of the functions are not 100% good, but changing the
name of _mktm_r() to something clearer (_mkgmtime_r()?) should come with
changing the name of the source file, so I decided to leave that as it
is... If you think that the names should change too, I could modify the
patch and extend it.
Regards,
FCh
-------------- next part --------------
From 0fbbb8b4518f44e033d8df6f1ec7d5efcd8cd91a Mon Sep 17 00:00:00 2001
From: Freddie Chopin <freddie.chopin@gmail.com>
Date: Wed, 3 Sep 2014 21:39:19 +0200
Subject: [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
---
newlib/libc/time/gmtime_r.c | 2 +-
newlib/libc/time/lcltime_r.c | 2 +-
newlib/libc/time/local.h | 3 +-
newlib/libc/time/mktm_r.c | 208 ++++++++++++++++++++++---------------------
4 files changed, 111 insertions(+), 104 deletions(-)
diff --git a/newlib/libc/time/gmtime_r.c b/newlib/libc/time/gmtime_r.c
index 14c9c76..4498d83 100644
--- a/newlib/libc/time/gmtime_r.c
+++ b/newlib/libc/time/gmtime_r.c
@@ -10,5 +10,5 @@ _DEFUN (gmtime_r, (tim_p, res),
_CONST time_t *__restrict tim_p _AND
struct tm *__restrict res)
{
- return (_mktm_r (tim_p, res, 1));
+ return (_mktm_r (tim_p, res));
}
diff --git a/newlib/libc/time/lcltime_r.c b/newlib/libc/time/lcltime_r.c
index 9e168aa..c9a1353 100644
--- a/newlib/libc/time/lcltime_r.c
+++ b/newlib/libc/time/lcltime_r.c
@@ -14,5 +14,5 @@ _DEFUN (localtime_r, (tim_p, res),
_CONST time_t *__restrict tim_p _AND
struct tm *__restrict res)
{
- return _mktm_r (tim_p, res, 0);
+ return _mklocaltm_r (tim_p, _mktm_r (tim_p, res));
}
diff --git a/newlib/libc/time/local.h b/newlib/libc/time/local.h
index 9d9ef87..5cfa116 100644
--- a/newlib/libc/time/local.h
+++ b/newlib/libc/time/local.h
@@ -19,7 +19,8 @@
#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));
+struct tm * _EXFUN (_mktm_r, (_CONST time_t *, struct tm *));
+struct tm * _EXFUN (_mklocaltm_r, (_CONST time_t *, struct tm *));
int _EXFUN (__tzcalc_limits, (int __year));
/* locks for multi-threading */
diff --git a/newlib/libc/time/mktm_r.c b/newlib/libc/time/mktm_r.c
index 2668efd..f2c435c 100644
--- a/newlib/libc/time/mktm_r.c
+++ b/newlib/libc/time/mktm_r.c
@@ -2,8 +2,8 @@
* 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>
+ * 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
@@ -34,10 +34,9 @@ static _CONST int days_per_year[4] = {
} ;
struct tm *
-_DEFUN (_mktm_r, (tim_p, res, is_gmtime),
+_DEFUN (_mktm_r, (tim_p, res),
_CONST time_t * tim_p _AND
- struct tm *res _AND
- int is_gmtime)
+ struct tm *res)
{
long days, rem;
time_t lcltime;
@@ -45,14 +44,13 @@ _DEFUN (_mktm_r, (tim_p, res, is_gmtime),
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)
+ while (rem < 0)
{
rem += SECSPERDAY;
--days;
@@ -62,8 +60,8 @@ _DEFUN (_mktm_r, (tim_p, res, is_gmtime),
rem -= SECSPERDAY;
++days;
}
-
- /* compute hour, min, and sec */
+
+ /* compute hour, min, and sec */
res->tm_hour = (int) (rem / SECSPERHOUR);
rem %= SECSPERHOUR;
res->tm_min = (int) (rem / SECSPERMIN);
@@ -110,105 +108,113 @@ _DEFUN (_mktm_r, (tim_p, res, is_gmtime),
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;
- if (!is_gmtime)
- {
- long offset;
- int hours, mins, secs;
+ return (res);
+}
- 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;
- }
+struct tm *
+_DEFUN (_mklocaltm_r, (tim_p, res),
+ _CONST time_t * tim_p _AND
+ struct tm *res)
+{
+ _CONST int year = res->tm_year + YEAR_BASE;
+ __tzinfo_type *_CONST tz = __gettzinfo ();
+ _CONST int yearleap = isleap(year);
+ _CONST int *_CONST ip = mon_lengths[yearleap];
+ long offset;
+ int hours, mins, secs;
+
+ 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 = 0;
+ res->tm_isdst = -1;
+ }
+ else
+ res->tm_isdst = 0;
- offset = (res->tm_isdst == 1
- ? tz->__tzrule[1].offset
- : tz->__tzrule[0].offset);
+ 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);
+ hours = (int) (offset / SECSPERHOUR);
+ offset = offset % SECSPERHOUR;
- res->tm_sec -= secs;
- res->tm_min -= mins;
- res->tm_hour -= hours;
+ mins = (int) (offset / SECSPERMIN);
+ secs = (int) (offset % SECSPERMIN);
- 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_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_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_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;
- }
+ res->tm_mon = 0;
+ res->tm_year += 1;
+ res->tm_yday = 0;
}
}
- else if (res->tm_hour < 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_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 -= 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];
+ 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;
+ TZ_UNLOCK;
return (res);
}
@@ -229,17 +235,17 @@ _DEFUN (__tzcalc_limits, (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) / 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 +
+ /* 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;
+ /* Convert to yday */
+ --days;
} else if (tz->__tzrule[i].ch == 'D')
days = year_days + tz->__tzrule[i].d;
else
@@ -254,7 +260,7 @@ _DEFUN (__tzcalc_limits, (year),
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;
@@ -267,7 +273,7 @@ _DEFUN (__tzcalc_limits, (year),
}
/* store the change-over time in GMT form by adding offset */
- tz->__tzrule[i].change = days * SECSPERDAY +
+ tz->__tzrule[i].change = days * SECSPERDAY +
tz->__tzrule[i].s + tz->__tzrule[i].offset;
}
--
1.8.1.msysgit.1
-------------- next part --------------
2014-09-03 Freddie Chopin <freddie_chopin@op.pl>
* libc/time/mktm_r.c (_mktm_r): move time zone related functionality
to new _mklocaltm_r(). Whitespace cleanup.
* libc/time/local.h: modify declaration of _mktm_r(), add declaration
of _mklocaltm_r().
* libc/time/gmtime_r.c (gmtime_r): modify call to _mktm_r().
* libc/time/lcltime_r.c (localtime_r): modify call to _mktm_r(), add
call to _mklocaltm_r().
More information about the Newlib
mailing list