From: Michael G. Schwern Date: Sat, 4 Oct 2008 19:12:50 +0000 (-0400) Subject: Update from y2038 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=b86b480f7301a8816081189c89b366a79ab9909f;p=p5sagit%2Fp5-mst-13.2.git Update from y2038 Configuration information split out into its own header. Added files to MANIFEST Turn off USE_SYSTEM_GMTIME, ours is more reliable and possibly faster. Fix type warnings found on Windows. Remove unnecessary use of floor() and ceil(). --- diff --git a/MANIFEST b/MANIFEST index 2872eeb..e8ea361 100644 --- a/MANIFEST +++ b/MANIFEST @@ -3600,6 +3600,9 @@ symbian/uid.pl Helper code for config.pl symbian/version.pl Helper code for config.pl symbian/xsbuild.pl Building extensions taint.c Tainting code +time64.c 64 bit clean time.h (code) +time64.h 64 bit clean time.h (header) +time64_config.h 64 bit clean time.h (configuration) t/base/cond.t See if conditionals work t/base/if.t See if if works t/base/lex.t See if lexical items work diff --git a/time64.c b/time64.c index 2cb6ad2..8d5820d 100644 --- a/time64.c +++ b/time64.c @@ -90,19 +90,26 @@ static const int dow_year_start[SOLAR_CYCLE_LENGTH] = { #define IS_LEAP(n) ((!(((n) + 1900) % 400) || (!(((n) + 1900) % 4) && (((n) + 1900) % 100))) != 0) #define WRAP(a,b,m) ((a) = ((a) < 0 ) ? ((b)--, (a) + (m)) : (a)) -#define SHOULD_USE_SYSTEM_LOCALTIME(a) ( \ - USE_SYSTEM_LOCALTIME && \ +#ifdef USE_SYSTEM_LOCALTIME +# define SHOULD_USE_SYSTEM_LOCALTIME(a) ( \ (a) <= SYSTEM_LOCALTIME_MAX && \ (a) >= SYSTEM_LOCALTIME_MIN \ ) -#define SHOULD_USE_SYSTEM_GMTIME(a) ( \ - USE_SYSTEM_GMTIME && \ +#else +# define SHOULD_USE_SYSTEM_LOCALTIME(a) (0) +#endif + +#ifdef USE_SYSTEM_GMTIME +# define SHOULD_USE_SYSTEM_GMTIME(a) ( \ (a) <= SYSTEM_GMTIME_MAX && \ (a) >= SYSTEM_GMTIME_MIN \ ) +#else +# define SHOULD_USE_SYSTEM_GMTIME(a) (0) +#endif -static int is_exception_century(Int64 year) +static int is_exception_century(Year year) { int is_exception = ((year % 100 == 0) && !(year % 400 == 0)); /* printf("is_exception_century: %s\n", is_exception ? "yes" : "no"); */ @@ -112,9 +119,9 @@ static int is_exception_century(Int64 year) Time64_T timegm64(struct TM *date) { - int days = 0; - Int64 seconds = 0; - Int64 year; + int days = 0; + Time64_T seconds = 0; + Year year; if( date->tm_year > 70 ) { year = 70; @@ -142,7 +149,7 @@ Time64_T timegm64(struct TM *date) { seconds += date->tm_min * 60; seconds += date->tm_sec; - return((Time64_T)seconds); + return(seconds); } @@ -352,9 +359,9 @@ struct tm * fake_gmtime_r(const time_t *clock, struct tm *result) { struct TM *gmtime64_r (const Time64_T *in_time, struct TM *p) { int v_tm_sec, v_tm_min, v_tm_hour, v_tm_mon, v_tm_wday; - Int64 v_tm_tday; + Time64_T v_tm_tday; int leap; - Int64 m; + Time64_T m; Time64_T time = *in_time; Year year = 70; int cycles = 0; @@ -406,7 +413,7 @@ struct TM *gmtime64_r (const Time64_T *in_time, struct TM *p) if (m >= 0) { /* Gregorian cycles, this is huge optimization for distant times */ - cycles = floor(m / (Time64_T) days_in_gregorian_cycle); + cycles = m / (Time64_T) days_in_gregorian_cycle; if( cycles ) { m -= (cycles * (Time64_T) days_in_gregorian_cycle); year += (cycles * years_in_gregorian_cycle); @@ -430,7 +437,7 @@ struct TM *gmtime64_r (const Time64_T *in_time, struct TM *p) year--; /* Gregorian cycles */ - cycles = ceil(m / (Time64_T) days_in_gregorian_cycle) + 1; + cycles = (m / (Time64_T) days_in_gregorian_cycle) + 1; if( cycles ) { m -= (cycles * (Time64_T) days_in_gregorian_cycle); year += (cycles * years_in_gregorian_cycle); @@ -461,10 +468,14 @@ struct TM *gmtime64_r (const Time64_T *in_time, struct TM *p) return NULL; } + /* At this point m is less than a year so casting to an int is safe */ p->tm_mday = (int) m + 1; - p->tm_yday = (int) julian_days_by_month[leap][v_tm_mon] + m; - p->tm_sec = v_tm_sec, p->tm_min = v_tm_min, p->tm_hour = v_tm_hour, - p->tm_mon = v_tm_mon, p->tm_wday = v_tm_wday; + p->tm_yday = julian_days_by_month[leap][v_tm_mon] + (int)m; + p->tm_sec = v_tm_sec; + p->tm_min = v_tm_min; + p->tm_hour = v_tm_hour; + p->tm_mon = v_tm_mon; + p->tm_wday = v_tm_wday; assert(check_tm(p)); @@ -503,7 +514,7 @@ struct TM *localtime64_r (const Time64_T *time, struct TM *local_tm) gm_tm.tm_year < (1902 - 1900) ) { - gm_tm.tm_year = safe_year(gm_tm.tm_year + 1900) - 1900; + gm_tm.tm_year = safe_year((Year)(gm_tm.tm_year + 1900)) - 1900; } safe_time = timegm64(&gm_tm); diff --git a/time64.h b/time64.h index 85e2ff5..e8c649b 100644 --- a/time64.h +++ b/time64.h @@ -1,68 +1,15 @@ #include +#include "time64_config.h" -#ifndef LOCALTIME64_H -# define LOCALTIME64_H +#ifndef TIME64_H +# define TIME64_H -/* Configuration. */ -/* Define as appropriate for your system */ -/* - HAS_GMTIME_R - Defined if your system has gmtime_r() - HAS_LOCALTIME_R - Defined if your system has localtime_r() +/* Set our custom types */ +typedef INT_64_T Int64; +typedef Int64 Time64_T; +typedef Int64 Year; - HAS_TIMEGM - Defined if your system has timegm() - - HAS_TM_TM_GMTOFF - Defined if your tm struct has a "tm_gmtoff" element. - - HAS_TM_TM_ZONE - Defined if your tm struct has a "tm_zone" element. - - SYSTEM_LOCALTIME_MAX - SYSTEM_LOCALTIME_MIN - SYSTEM_GMTIME_MAX - SYSTEM_GMTIME_MIN - Maximum and minimum values your system's gmtime() and localtime() - can handle. - - USE_SYSTEM_LOCALTIME - USE_SYSTEM_GMTIME - Should we use the system functions if the time is inside their range? - - USE_TM64 - Should we use a 64 bit safe tm struct which can handle a - year range greater than 2 billion? -*/ - -#define SYSTEM_LOCALTIME_MAX LOCALTIME_MAX -#define SYSTEM_LOCALTIME_MIN LOCALTIME_MIN -#define SYSTEM_GMTIME_MAX GMTIME_MAX -#define SYSTEM_GMTIME_MIN GMTIME_MIN - -/* It'll be faster */ -#define USE_SYSTEM_LOCALTIME 1 -#define USE_SYSTEM_GMTIME 1 - -/* Let's get all the time */ -#define USE_TM64 - -#ifdef USE_TM64 -#define TM TM64 -#else -#define TM tm -#endif - -/* 64 bit types. Set as appropriate for your system. */ -typedef Quad_t Time64_T; -typedef Quad_t Int64; -typedef Int64 Year; - -struct TM *gmtime64_r (const Time64_T *, struct TM *); -struct TM *localtime64_r (const Time64_T *, struct TM *); -Time64_T timegm64 (struct TM *); /* A copy of the tm struct but with a 64 bit year */ struct TM64 { @@ -86,7 +33,21 @@ struct TM64 { }; -/* Not everyone has gm/localtime_r() */ +/* Decide which tm struct to use */ +#ifdef USE_TM64 +#define TM TM64 +#else +#define TM tm +#endif + + +/* Declare public functions */ +struct TM *gmtime64_r (const Time64_T *, struct TM *); +struct TM *localtime64_r (const Time64_T *, struct TM *); +Time64_T timegm64 (struct TM *); + + +/* Not everyone has gm/localtime_r(), provide a replacement */ #ifdef HAS_LOCALTIME_R # define LOCALTIME_R(clock, result) localtime_r(clock, result) #else diff --git a/time64_config.h b/time64_config.h new file mode 100644 index 0000000..c22a115 --- /dev/null +++ b/time64_config.h @@ -0,0 +1,75 @@ +#ifndef TIME64_CONFIG_H +# define TIME64_CONFIG_H + +/* Configuration + ------------- + Define as appropriate for your system. + Sensible defaults provided. +*/ + +/* INT_64_T + A 64 bit integer type to use to store time and others. + Must be defined. +*/ +#define INT_64_T Quad_t + + +/* USE_TM64 + Should we use a 64 bit safe replacement for tm? This will + let you go past year 2 billion but the struct will be incompatible + with tm. Conversion functions will be provided. +*/ +#define USE_TM64 + + +/* Availability of system functions. + + HAS_GMTIME_R + Define if your system has gmtime_r() + + HAS_LOCALTIME_R + Define if your system has localtime_r() + + HAS_TIMEGM + Define if your system has timegm(), a GNU extension. +*/ +/* Set in config.h */ + + +/* Details of non-standard tm struct elements. + + HAS_TM_TM_GMTOFF + True if your tm struct has a "tm_gmtoff" element. + A BSD extension. + + HAS_TM_TM_ZONE + True if your tm struct has a "tm_zone" element. + A BSD extension. +*/ +/* Set in config.h */ + + +/* USE_SYSTEM_LOCALTIME + USE_SYSTEM_GMTIME + Should we use the system functions if the time is inside their range? + Your system localtime() is probably more accurate, but our gmtime() is + fast and safe. +*/ +#define USE_SYSTEM_LOCALTIME +/* #define USE_SYSTEM_GMTIME */ + + +/* SYSTEM_LOCALTIME_MAX + SYSTEM_LOCALTIME_MIN + SYSTEM_GMTIME_MAX + SYSTEM_GMTIME_MIN + Maximum and minimum values your system's gmtime() and localtime() + can handle. We will use your system functions if the time falls + inside these ranges. +*/ +#define SYSTEM_LOCALTIME_MAX LOCALTIME_MAX +#define SYSTEM_LOCALTIME_MIN LOCALTIME_MIN +#define SYSTEM_GMTIME_MAX GMTIME_MAX +#define SYSTEM_GMTIME_MIN GMTIME_MIN + +#endif TIME64_CONFIG_H