This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Talk to Leo about dev.perl.org, not Rafael
[perl5.git] / Porting / timecheck.c
1 /* A helper tool for perl's 2038 support.
2  *      See Porting/README.y2038 for details
3  */
4
5 #include <sys/types.h>
6 #include <stdio.h>
7 #include <time.h>
8 #include <errno.h>
9 #include <values.h>
10
11 int opt_v = 0;
12 int i;
13 struct tm *tmp;
14 time_t pt, pt_max, pt_min;
15
16 static char hexbuf[80];
17 char *hex (time_t t)
18 {
19     if ((long long)t < 0)
20         sprintf (hexbuf, " -0x%016lx", -t);
21     else
22         sprintf (hexbuf, "  0x%016lx",  t);
23     return (hexbuf);
24     } /* hex */
25
26 void gm_check (time_t t, int min_year, int max_year)
27 {
28     tmp = gmtime (&t);
29     if ( tmp == NULL ||
30         /* Check tm_year overflow */
31          tmp->tm_year < min_year || tmp->tm_year > max_year) {
32         if (opt_v)
33             fprintf (stderr, "gmtime (%ld) failed with errno %d\n", t, errno);
34         }
35     else {
36         if (opt_v)
37             fprintf (stderr, "%3d:%s: %12ld-%02d-%02d %02d:%02d:%02d\n",
38                 i, hex (t),
39                 tmp->tm_year + 1900, tmp->tm_mon + 1, tmp->tm_mday,
40                 tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
41         pt = t;
42         }
43     } /* gm_check */
44
45 int check_gm_max ()
46 {
47     tmp = NULL;
48     pt  = 0;
49     if (tmp == NULL || tmp->tm_year < 0) {
50         for (i = 63; i >= 0; i--) {
51             time_t x = pt | ((time_t)1 << i);
52             if (x < 0 || x < pt) continue;
53             gm_check (x, 69, 0x7fffffff);
54             }
55         }
56     pt_max = pt;
57     return (0);
58     } /* check_gm_max */
59
60 int check_gm_min ()
61 {
62     tmp = NULL;
63     pt  = 0;
64     if (tmp == NULL) {
65         for (i = 36; i >= 0; i--) {
66             time_t x = pt - ((time_t)1 << i);
67             if (x > 0) continue;
68             gm_check (x, -1900, 70);
69             }
70         }
71     pt_min = pt;
72     return (0);
73     } /* check_gm_min */
74
75 void lt_check (time_t t, int min_year, int max_year)
76 {
77     if (sizeof (time_t) > 4 && t > 0x7ffffffffffff000LL)
78         tmp = NULL;
79     else
80         tmp = localtime (&t);
81     if ( tmp == NULL ||
82         /* Check tm_year overflow */
83          tmp->tm_year < min_year || tmp->tm_year > max_year) {
84         if (opt_v)
85             fprintf (stderr, "localtime (%ld) failed with errno %d\n", t, errno);
86         }
87     else {
88         if (opt_v)
89             fprintf (stderr, "%3d:%s: %12ld-%02d-%02d %02d:%02d:%02d\n",
90                 i, hex (t),
91                 tmp->tm_year + 1900, tmp->tm_mon + 1, tmp->tm_mday,
92                 tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
93         pt = t;
94         }
95     } /* lt_check */
96
97 int check_lt_max ()
98 {
99     tmp = NULL;
100     pt  = 0;
101     if (tmp == NULL || tmp->tm_year < 0) {
102         for (i = 63; i >= 0; i--) {
103             time_t x = pt | ((time_t)1 << i);
104             if (x < 0 || x < pt) continue;
105             lt_check (x, 69, 0x7fffffff);
106             }
107         }
108     pt_max = pt;
109     return (0);
110     } /* check_lt_max */
111
112 int check_lt_min ()
113 {
114     tmp = NULL;
115     pt  = 0;
116     if (tmp == NULL) {
117         for (i = 36; i >= 0; i--) {
118             time_t x = pt - ((time_t)1 << i);
119             if (x > 0) continue;
120             lt_check (x, -1900, 70);
121             }
122         }
123     pt_min = pt;
124     return (0);
125     } /* check_lt_min */
126
127 int main (int argc, char *argv[])
128 {
129     time_t gm_max, gm_min, lt_max, lt_min;
130     if (argc > 1 && strcmp (argv[1], "-v") == 0) opt_v++;
131
132     check_gm_max (); gm_max = pt_max;
133     check_gm_min (); gm_min = pt_min;
134     check_lt_max (); lt_max = pt_max;
135     check_lt_min (); lt_min = pt_min;
136
137     opt_v++;
138     printf ("======================\n");
139     printf ("Sizeof time_t = %ld\n", (i = sizeof (time_t)));
140     printf ("gmtime () boundaries:\n");
141     gm_check (gm_max,    69, 0x7fffffff);
142     gm_check (gm_min, -1900,         70);
143     printf ("localtime () boundaries:\n");
144     lt_check (lt_max,    69, 0x7fffffff);
145     lt_check (lt_min, -1900,         70);
146     printf ("Configure variables:\n");
147     printf ("sGMTIME_max='%ld'\n",    gm_max);
148     printf ("sGMTIME_min='%ld'\n",    gm_min);
149     printf ("sLOCALTIME_max='%ld'\n", lt_max);
150     printf ("sLOCALTIME_min='%ld'\n", lt_min);
151     return (0);
152     } /* main */