Update from y2038
Michael G. Schwern [Mon, 29 Sep 2008 15:05:17 +0000 (11:05 -0400)]
Work around a system that doesn't have gm/localtime_r().  This replaces Perl's
own gm/localtime() wrapper which couldn't be called outside a PP anyway
because it needs my_perl.

localtime64.c
localtime64.h
reentr.c
reentr.h
reentr.pl

index 72bd68f..176cc40 100644 (file)
@@ -258,6 +258,40 @@ int _safe_year(Year year)
 }
 
 
+/* Simulate localtime_r() to the best of our ability */
+struct tm * fake_localtime_r(const time_t *clock, struct tm *result) {
+    const struct tm *static_result = localtime(clock);
+
+    assert(result != NULL);
+
+    if( static_result == NULL ) {
+        memset(result, 0, sizeof(*result));
+        return NULL;
+    }
+    else {
+        memcpy(result, static_result, sizeof(*result));
+        return result;
+    }
+}
+
+
+/* Simulate gmtime_r() to the best of our ability */
+struct tm * fake_gmtime_r(const time_t *clock, struct tm *result) {
+    const struct tm *static_result = gmtime(clock);
+
+    assert(result != NULL);
+
+    if( static_result == NULL ) {
+        memset(result, 0, sizeof(*result));
+        return NULL;
+    }
+    else {
+        memcpy(result, static_result, sizeof(*result));
+        return 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;
@@ -267,10 +301,12 @@ struct tm *gmtime64_r (const Time64_T *in_time, struct tm *p)
     Time64_T time = *in_time;
     Year year = 70;
 
+    assert(p != NULL);
+
     /* Use the system gmtime() if time_t is small enough */
     if( SHOULD_USE_SYSTEM_GMTIME(*in_time) ) {
         time_t safe_time = *in_time;
-        gmtime_r(&safe_time, p);
+        GMTIME_R(&safe_time, p);
         assert(_check_tm(p));
         return p;
     }
@@ -379,10 +415,12 @@ struct tm *localtime64_r (const Time64_T *time, struct tm *local_tm)
     Year orig_year;
     int month_diff;
 
+    assert(local_tm != NULL);
+
     /* Use the system localtime() if time_t is small enough */
     if( SHOULD_USE_SYSTEM_LOCALTIME(*time) ) {
         safe_time = *time;
-        localtime_r(&safe_time, local_tm);
+        LOCALTIME_R(&safe_time, local_tm);
         assert(_check_tm(local_tm));
         return local_tm;
     }
@@ -400,7 +438,7 @@ struct tm *localtime64_r (const Time64_T *time, struct tm *local_tm)
     }
 
     safe_time = TIMEGM(&gm_tm);
-    if( localtime_r(&safe_time, local_tm) == NULL )
+    if( LOCALTIME_R(&safe_time, local_tm) == NULL )
         return NULL;
 
     local_tm->tm_year = orig_year;
index 3771977..db8ddbf 100644 (file)
@@ -4,6 +4,12 @@
 /* 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()
+
    HAS_TIMEGM
    Defined if your system has timegm()
 
@@ -43,4 +49,17 @@ 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() */
+#ifdef HAS_LOCALTIME_R
+#    define LOCALTIME_R(clock, result) localtime_r(clock, result)
+#else
+#    define LOCALTIME_R(clock, result) fake_localtime_r(clock, result)
+#endif
+#ifdef HAS_GMTIME_R
+#    define GMTIME_R(clock, result)    gmtime_r(clock, result)
+#else
+#    define GMTIME_R(clock, result)    fake_gmtime_r(clock, result)
+#endif
+
 #endif
index 25fccf8..8d9ab2a 100644 (file)
--- a/reentr.c
+++ b/reentr.c
@@ -115,10 +115,6 @@ Perl_reentrant_size(pTHX) {
 #       endif
 #   endif 
 #endif /* HAS_GETSPNAM_R */
-#ifdef HAS_GMTIME_R
-#endif /* HAS_GMTIME_R */
-#ifdef HAS_LOCALTIME_R
-#endif /* HAS_LOCALTIME_R */
 #ifdef HAS_RANDOM_R
 #endif /* HAS_RANDOM_R */
 #ifdef HAS_READDIR_R
@@ -205,10 +201,6 @@ Perl_reentrant_init(pTHX) {
 #   endif
        Newx(PL_reentrant_buffer->_spent_buffer, PL_reentrant_buffer->_spent_size, char);
 #endif /* HAS_GETSPNAM_R */
-#ifdef HAS_GMTIME_R
-#endif /* HAS_GMTIME_R */
-#ifdef HAS_LOCALTIME_R
-#endif /* HAS_LOCALTIME_R */
 #ifdef HAS_RANDOM_R
 #endif /* HAS_RANDOM_R */
 #ifdef HAS_READDIR_R
@@ -280,10 +272,6 @@ Perl_reentrant_free(pTHX) {
 #ifdef HAS_GETSPNAM_R
        Safefree(PL_reentrant_buffer->_spent_buffer);
 #endif /* HAS_GETSPNAM_R */
-#ifdef HAS_GMTIME_R
-#endif /* HAS_GMTIME_R */
-#ifdef HAS_LOCALTIME_R
-#endif /* HAS_LOCALTIME_R */
 #ifdef HAS_RANDOM_R
 #endif /* HAS_RANDOM_R */
 #ifdef HAS_READDIR_R
index 05b06f8..e66abd9 100644 (file)
--- a/reentr.h
+++ b/reentr.h
 #define REENTRANT_PROTO_S_SBIE 69
 #define REENTRANT_PROTO_S_SBW  70
 #define REENTRANT_PROTO_S_TISBI        71
-#define REENTRANT_PROTO_S_TS   72
-#define REENTRANT_PROTO_S_TSBI 73
-#define REENTRANT_PROTO_S_TSBIE        74
-#define REENTRANT_PROTO_S_TWISBIE      75
-#define REENTRANT_PROTO_V_D    76
-#define REENTRANT_PROTO_V_H    77
-#define REENTRANT_PROTO_V_ID   78
+#define REENTRANT_PROTO_S_TSBI 72
+#define REENTRANT_PROTO_S_TSBIE        73
+#define REENTRANT_PROTO_S_TWISBIE      74
+#define REENTRANT_PROTO_V_D    75
+#define REENTRANT_PROTO_V_H    76
+#define REENTRANT_PROTO_V_ID   77
 
 /* Defines for indicating which special features are supported. */
 
@@ -740,12 +739,6 @@ typedef struct {
        FILE*   _spent_fptr;
 #   endif
 #endif /* HAS_GETSPNAM_R */
-#ifdef HAS_GMTIME_R
-       struct tm _gmtime_struct;
-#endif /* HAS_GMTIME_R */
-#ifdef HAS_LOCALTIME_R
-       struct tm _localtime_struct;
-#endif /* HAS_LOCALTIME_R */
 #ifdef HAS_RANDOM_R
        struct random_data _random_struct;
 #   if RANDOM_R_PROTO == REENTRANT_PROTO_I_iS
@@ -1330,30 +1323,6 @@ typedef struct {
 #   endif /* HAS_GETSPNAM */
 #endif /* HAS_GETSPNAM_R */
 
-#ifdef HAS_GMTIME_R
-#  if defined(PERL_REENTR_API) && (PERL_REENTR_API+0 == 1)
-#   undef gmtime
-#   if !defined(gmtime) && GMTIME_R_PROTO == REENTRANT_PROTO_S_TS
-#       define gmtime(a) (gmtime_r(a, &PL_reentrant_buffer->_gmtime_struct) ? &PL_reentrant_buffer->_gmtime_struct : 0)
-#  endif /* if defined(PERL_REENTR_API) && (PERL_REENTR_API+0 == 1) */
-#   if !defined(gmtime) && GMTIME_R_PROTO == REENTRANT_PROTO_I_TS
-#       define gmtime(a) (gmtime_r(a, &PL_reentrant_buffer->_gmtime_struct) == 0 ? &PL_reentrant_buffer->_gmtime_struct : 0)
-#  endif /* if defined(PERL_REENTR_API) && (PERL_REENTR_API+0 == 1) */
-#   endif /* HAS_GMTIME */
-#endif /* HAS_GMTIME_R */
-
-#ifdef HAS_LOCALTIME_R
-#  if defined(PERL_REENTR_API) && (PERL_REENTR_API+0 == 1)
-#   undef localtime
-#   if !defined(localtime) && LOCALTIME_R_PROTO == REENTRANT_PROTO_S_TS
-#       define localtime(a) (L_R_TZSET localtime_r(a, &PL_reentrant_buffer->_localtime_struct) ? &PL_reentrant_buffer->_localtime_struct : 0)
-#  endif /* if defined(PERL_REENTR_API) && (PERL_REENTR_API+0 == 1) */
-#   if !defined(localtime) && LOCALTIME_R_PROTO == REENTRANT_PROTO_I_TS
-#       define localtime(a) (L_R_TZSET localtime_r(a, &PL_reentrant_buffer->_localtime_struct) == 0 ? &PL_reentrant_buffer->_localtime_struct : 0)
-#  endif /* if defined(PERL_REENTR_API) && (PERL_REENTR_API+0 == 1) */
-#   endif /* HAS_LOCALTIME */
-#endif /* HAS_LOCALTIME_R */
-
 #ifdef HAS_RANDOM_R
 #  if defined(PERL_REENTR_API) && (PERL_REENTR_API+0 == 1)
 #   undef random
index ea327a0..89795cd 100644 (file)
--- a/reentr.pl
+++ b/reentr.pl
@@ -504,7 +504,7 @@ EOF
 EOF
            pushssif $endif;
        }
-        elsif ($func =~ /^(drand48|gmtime|localtime|random|srandom)$/) {
+        elsif ($func =~ /^(drand48|random|srandom)$/) {
            pushssif $ifdef;
            push @struct, <<EOF;
        $seent{$func} _${func}_struct;
@@ -716,9 +716,6 @@ EOF
            }
 
            my $call = "${func}_r($v$w)";
-           if ($func eq 'localtime') {
-               $call = "L_R_TZSET $call";
-           }
 
             # Must make OpenBSD happy
             my $memzero = '';
@@ -1124,8 +1121,6 @@ getservbyname CC|netdb    |struct servent |I_CCSBWR|S_CCSBI|I_CCSD|D=struct servent
 getservbyport IC|netdb |struct servent |I_ICSBWR|S_ICSBI|I_ICSD|D=struct servent_data*
 getservent     |netdb  |struct servent |I_SBWR|I_SBI|S_SBI|I_SD|D=struct servent_data*
 getspnam C     |shadow |struct spwd    |I_CSBWR|S_CSBI
-gmtime T       |time   |struct tm      |S_TS|I_TS|T=const time_t*
-localtime T    |time   |struct tm      |S_TS|I_TS|T=const time_t*
 random         |stdlib |struct random_data|I_iS|I_lS|I_St|i=int*|l=long*|t=int32_t*
 readdir T      |dirent |struct dirent  |I_TSR|I_TS|T=DIR*
 readdir64 T    |dirent |struct dirent64|I_TSR|I_TS|T=DIR*