[tz] [PATCH] Remove attempt to support floating-point time_t.
Paul Eggert
eggert at cs.ucla.edu
Mon Aug 12 08:47:17 UTC 2013
Here's a proposed patch to remove the tz code's attempt to support
floating-point time_t. This has the benefit of simplifying
the code and making maintenance easier. Comments welcome
(particularly if you know of any real systems that have
floating-point time_t!). I've pushed this to the experimental
github repository.
-----
It wasn't tested and probably never worked, no platform used it,
and the latest POSIX no longer allows it.
* Makefile (typecheck): Don't check time_t being 'double'.
* Theory: Document the change.
* difftime.c (difftime):
* localtime.c (differ_by_repeat, tzload, timesub, time2sub):
* private.h (time_t_min, time_t_max):
* zdump.c (absolute_min_time, absolute_max_time, tformat):
Don't try to support floating-point time_t.
* localtime.c, private.h, zdump.c: Don't include float.h.
* localtime.c (truncate_time, double_to_time):
* private.h (TYPE_INTEGRAL):
* zdump.c (checkabsolutes):
Remove; no longer needed. All uses removed.
* zdump.8 (LIMITATIONS): Remove discussion of floating-point time_t.
---
Makefile | 3 +--
Theory | 9 ++++-----
difftime.c | 10 +---------
localtime.c | 62 ++++++-------------------------------------------------------
private.h | 28 ++--------------------------
zdump.8 | 7 -------
zdump.c | 37 ++----------------------------------
7 files changed, 16 insertions(+), 140 deletions(-)
diff --git a/Makefile b/Makefile
index 8b033a6..db7f56e 100644
--- a/Makefile
+++ b/Makefile
@@ -121,7 +121,6 @@ LDLIBS=
# -DNO_RUN_TIME_WARNINGS_ABOUT_YEAR_2000_PROBLEMS_THANK_YOU=1
# if you do not want run time warnings about formats that may cause
# year 2000 grief
-# -DTIME_T_FLOATING=1 if your time_t (or time_tz) is floating point
# -Dtime_tz=\"T\" to use T as the time_t type, rather than the system time_t
# -DTZ_DOMAIN=\"foo\" to use "foo" for gettext domain name; default is "tz"
# -TTZ_DOMAINDIR=\"/path\" to use "/path" for gettext directory;
@@ -541,7 +540,7 @@ tzdata$(VERSION).tar.gz.asc: tzdata$(VERSION).tar.gz
typecheck:
make clean
- for i in "long long" unsigned double; \
+ for i in "long long" unsigned; \
do \
make CFLAGS="-DTYPECHECK -D__time_t_defined -D_TIME_T \"-Dtime_t=$$i\"" ; \
./zdump -v Europe/Rome ; \
diff --git a/Theory b/Theory
index 1b5374a..b4bd4c2 100644
--- a/Theory
+++ b/Theory
@@ -104,11 +104,10 @@ POSIX has the following properties and limitations.
new implementations these days typically use a signed 64-bit integer.
Unsigned 32-bit integers are used on one or two platforms,
and 36-bit integers are also used occasionally.
- Although POSIX.1-2013 requires time_t to be an integer type,
- earlier POSIX versions also allowed time_t to be a floating-point type.
- No known platforms have a floating-point time_t and although
- the tz code attempts to support floating-point time_t this has not
- been tested and will probably be removed at some point.
+ Although earlier POSIX versions allowed time_t to be a
+ floating-point type, this was not supported by any practical
+ systems, and POSIX.1-2013 and the tz code both require time_t
+ to be an integer type.
These are the extensions that have been made to the POSIX functions:
diff --git a/difftime.c b/difftime.c
index fcd18ce..449cdf0 100644
--- a/difftime.c
+++ b/difftime.c
@@ -5,7 +5,7 @@
/*LINTLIBRARY*/
-#include "private.h" /* for time_t, TYPE_INTEGRAL, and TYPE_SIGNED */
+#include "private.h" /* for time_t and TYPE_SIGNED */
double ATTRIBUTE_CONST
difftime(const time_t time1, const time_t time0)
@@ -16,15 +16,8 @@ difftime(const time_t time1, const time_t time0)
*/
if (sizeof (double) > sizeof (time_t))
return (double) time1 - (double) time0;
- if (!TYPE_INTEGRAL(time_t)) {
- /*
- ** time_t is floating.
- */
- return time1 - time0;
- }
if (!TYPE_SIGNED(time_t)) {
/*
- ** time_t is integral and unsigned.
** The difference of two unsigned values can't overflow
** if the minuend is greater than or equal to the subtrahend.
*/
@@ -33,7 +26,6 @@ difftime(const time_t time1, const time_t time0)
else return -(double) (time0 - time1);
}
/*
- ** time_t is integral and signed.
** Handle cases where both time1 and time0 have the same sign
** (meaning that their difference cannot overflow).
*/
diff --git a/localtime.c b/localtime.c
index 9600901..5312ad9 100644
--- a/localtime.c
+++ b/localtime.c
@@ -13,7 +13,6 @@
#include "private.h"
#include "tzfile.h"
#include "fcntl.h"
-#include "float.h" /* for FLT_MAX and DBL_MAX */
#ifndef TZ_ABBR_MAX_LEN
#define TZ_ABBR_MAX_LEN 16
@@ -318,9 +317,8 @@ settzname(void)
static int
differ_by_repeat(const time_t t1, const time_t t0)
{
- if (TYPE_INTEGRAL(time_t) &&
- TYPE_BIT(time_t) - TYPE_SIGNED(time_t) < SECSPERREPEAT_BITS)
- return 0;
+ if (TYPE_BIT(time_t) - TYPE_SIGNED(time_t) < SECSPERREPEAT_BITS)
+ return 0;
return t1 - t0 == SECSPERREPEAT;
}
@@ -527,9 +525,9 @@ tzload(register const char *name, register struct state *const sp,
for (i = 0; i < nread; ++i)
up->buf[i] = p[i];
/*
- ** If this is a narrow integer time_t system, we're done.
+ ** If this is a narrow time_t system, we're done.
*/
- if (stored >= (int) sizeof(time_t) && TYPE_INTEGRAL(time_t))
+ if (stored >= (int) sizeof(time_t))
break;
}
if (doextend && nread > 2 &&
@@ -1254,35 +1252,6 @@ tzset(void)
settzname();
}
-/* Return T with any fractional part discarded. */
-static time_t
-truncate_time(time_t t)
-{
- /*
- ** If time_t is floating-point, convert it to integer and
- ** back; this discards the fraction. Avoid using <math.h>
- ** functions, as we don't want to depend on <math.h>. Use <,
- ** not <=, when comparing against *_MIN and *_MAX values, as
- ** this avoids undefined behavior when, for example,
- ** INTMAX_MAX is converted to a larger time_t value before it
- ** is compared.
- **
- ** On all platforms that we know of (1) it is safe to compare
- ** INTMAX_MIN and INTMAX_MAX to floating-point values without
- ** worrying about undefined behavior due to floating-point
- ** overflow on conversion, and (2) any time_t value outside
- ** intmax_t range is an integer so we can simply return it.
- ** We know of no simple, portable way to check these assumptions.
- ** If you know of a counterexample platform, please report a bug.
- */
- if (!TYPE_INTEGRAL(time_t) && INTMAX_MIN < t && t < INTMAX_MAX) {
- intmax_t i = t;
- return i;
- }
-
- return t;
-}
-
/*
** The easy way to behave "as if no library function calls" localtime
** is to not call it--so we drop its guts into "localsub", which can be
@@ -1318,8 +1287,7 @@ localsub(const time_t *const timep, const int_fast32_t offset,
seconds = sp->ats[0] - t;
else seconds = t - sp->ats[sp->timecnt - 1];
--seconds;
- years = (truncate_time (seconds / SECSPERREPEAT + 1)
- * YEARSPERREPEAT);
+ years = (seconds / SECSPERREPEAT + 1) * YEARSPERREPEAT;
seconds = years * AVGSECSPERYEAR;
if (t < sp->ats[0])
newt += seconds;
@@ -1457,18 +1425,6 @@ offtime(const time_t *const timep, const long offset)
#endif /* defined STD_INSPIRED */
/*
-** Convert T to time_t, truncating toward zero if time_t is integral.
-** On most platforms, double_to_time(0.5) returns 0; the exceptions are
-** the rare platforms where time_t is floating.
-*/
-
-static time_t
-double_to_time(double t)
-{
- return t;
-}
-
-/*
** Return the number of leap years through the end of the given year
** where, to make the math easy, the answer for year zero is defined as zero.
*/
@@ -1549,9 +1505,8 @@ timesub(const time_t *const timep, const int_fast32_t offset,
}
{
register int_fast32_t seconds;
- register time_t half_second = double_to_time(0.5);
- seconds = tdays * SECSPERDAY + half_second;
+ seconds = tdays * SECSPERDAY;
tdays = seconds / SECSPERDAY;
rem += seconds - tdays * SECSPERDAY;
}
@@ -1811,11 +1766,6 @@ time2sub(struct tm *const tmp,
if (!TYPE_SIGNED(time_t)) {
lo = 0;
hi = lo - 1;
- } else if (!TYPE_INTEGRAL(time_t)) {
- if (sizeof(time_t) > sizeof(float))
- hi = (time_t) DBL_MAX;
- else hi = (time_t) FLT_MAX;
- lo = -hi;
} else {
lo = 1;
for (i = 0; i < (int) TYPE_BIT(time_t) - 1; ++i)
diff --git a/private.h b/private.h
index 5f4384e..8c1cda7 100644
--- a/private.h
+++ b/private.h
@@ -74,7 +74,6 @@
#include "sys/types.h" /* for time_t */
#include "stdio.h"
#include "errno.h"
-#include "float.h" /* for FLT_MAX and DBL_MAX */
#include "string.h"
#include "limits.h" /* for CHAR_BIT et al. */
#include "time.h"
@@ -318,37 +317,14 @@ const char * scheck(const char * string, const char * format);
/* The minimum and maximum finite time values. */
static time_t const time_t_min =
- ((time_t) 0.5 == 0.5
- ? (sizeof (time_t) == sizeof (float) ? (time_t) -FLT_MAX
- : sizeof (time_t) == sizeof (double) ? (time_t) -DBL_MAX
- : sizeof (time_t) == sizeof (long double) ? (time_t) -LDBL_MAX
- : 0)
-#ifndef TIME_T_FLOATING
- : (time_t) -1 < 0
+ (TYPE_SIGNED(time_t)
? (time_t) -1 << (CHAR_BIT * sizeof (time_t) - 1)
-#endif
: 0);
static time_t const time_t_max =
- ((time_t) 0.5 == 0.5
- ? (sizeof (time_t) == sizeof (float) ? (time_t) FLT_MAX
- : sizeof (time_t) == sizeof (double) ? (time_t) DBL_MAX
- : sizeof (time_t) == sizeof (long double) ? (time_t) LDBL_MAX
- : -1)
-#ifndef TIME_T_FLOATING
- : (time_t) -1 < 0
+ (TYPE_SIGNED(time_t)
? - (~ 0 < 0) - ((time_t) -1 << (CHAR_BIT * sizeof (time_t) - 1))
-#endif
: -1);
-/*
-** Since the definition of TYPE_INTEGRAL contains floating point numbers,
-** it cannot be used in preprocessor directives.
-*/
-
-#ifndef TYPE_INTEGRAL
-#define TYPE_INTEGRAL(type) (((type) 0.5) != 0.5)
-#endif /* !defined TYPE_INTEGRAL */
-
#ifndef INT_STRLEN_MAXIMUM
/*
** 302 / 1000 is log10(2.0) rounded up.
diff --git a/zdump.8 b/zdump.8
index f253e81..af3277d 100644
--- a/zdump.8
+++ b/zdump.8
@@ -57,13 +57,6 @@ the program cuts off verbose output near the starts of the years \-500 and 2500.
Cut off verbose output at the start of the given time(s),
given in decimal seconds since 1970-01-01 00:00:00 UTC.
.SH LIMITATIONS
-The
-.B \-v
-and
-.B \-V
-options may not be used on systems with floating-point time_t values
-that are neither float nor double.
-.PP
Time discontinuities are found by sampling the results returned by localtime
at twelve-hour intervals.
This works in all real-world cases;
diff --git a/zdump.c b/zdump.c
index be0a496..788020a 100644
--- a/zdump.c
+++ b/zdump.c
@@ -23,7 +23,6 @@
#include "sys/types.h" /* for time_t */
#include "time.h" /* for struct tm */
#include "stdlib.h" /* for exit, malloc, atoi */
-#include "float.h" /* for FLT_MAX and DBL_MAX */
#include "limits.h" /* for CHAR_BIT, LLONG_MAX */
#include "ctype.h" /* for isalpha et al. */
#ifndef isascii
@@ -193,26 +192,12 @@ extern char * tzname[2];
/* The minimum and maximum finite time values. */
static time_t const absolute_min_time =
- ((time_t) 0.5 == 0.5
- ? (sizeof (time_t) == sizeof (float) ? (time_t) -FLT_MAX
- : sizeof (time_t) == sizeof (double) ? (time_t) -DBL_MAX
- : sizeof (time_t) == sizeof (long double) ? (time_t) -LDBL_MAX
- : 0)
-#ifndef TIME_T_FLOATING
- : (time_t) -1 < 0
+ ((time_t) -1 < 0
? (time_t) -1 << (CHAR_BIT * sizeof (time_t) - 1)
-#endif
: 0);
static time_t const absolute_max_time =
- ((time_t) 0.5 == 0.5
- ? (sizeof (time_t) == sizeof (float) ? (time_t) FLT_MAX
- : sizeof (time_t) == sizeof (double) ? (time_t) DBL_MAX
- : sizeof (time_t) == sizeof (long double) ? (time_t) LDBL_MAX
- : -1)
-#ifndef TIME_T_FLOATING
- : (time_t) -1 < 0
+ ((time_t) -1 < 0
? - (~ 0 < 0) - ((time_t) -1 << (CHAR_BIT * sizeof (time_t) - 1))
-#endif
: -1);
static size_t longest;
static char * progname;
@@ -223,7 +208,6 @@ static void abbrok(const char * abbrp, const char * zone);
static intmax_t delta(struct tm * newp, struct tm * oldp) ATTRIBUTE_PURE;
static void dumptime(const struct tm * tmp);
static time_t hunt(char * name, time_t lot, time_t hit);
-static void checkabsolutes(void);
static void show(char * zone, time_t t, int v);
static const char * tformat(void);
static time_t yeartot(intmax_t y) ATTRIBUTE_PURE;
@@ -383,7 +367,6 @@ main(int argc, char *argv[])
exit(EXIT_FAILURE);
}
}
- checkabsolutes();
if (cutarg != NULL || cuttimes == NULL) {
cutlotime = yeartot(cutloyear);
cuthitime = yeartot(cuthiyear);
@@ -504,17 +487,6 @@ main(int argc, char *argv[])
return EXIT_FAILURE;
}
-static void
-checkabsolutes(void)
-{
- if (absolute_max_time < absolute_min_time) {
- (void) fprintf(stderr,
-_("%s: use of -v on system with floating time_t other than float or double\n"),
- progname);
- exit(EXIT_FAILURE);
- }
-}
-
static time_t
yeartot(const intmax_t y)
{
@@ -666,11 +638,6 @@ abbr(struct tm *tmp)
static const char *
tformat(void)
{
- if (0.5 == (time_t) 0.5) { /* floating */
- if (sizeof (time_t) > sizeof (double))
- return "%Lg";
- return "%g";
- }
if (0 > (time_t) -1) { /* signed */
if (sizeof (time_t) == sizeof (intmax_t))
return "%"PRIdMAX;
--
1.8.1.2
More information about the tz
mailing list