Upgrade diffutils from 3.0 to 3.2 on the vendor branch
[dragonfly.git] / contrib / diffutils / lib / mktime.c
1 /* -*- buffer-read-only: t -*- vi: set ro: */
2 /* DO NOT EDIT! GENERATED AUTOMATICALLY! */
3 /* Convert a `struct tm' to a time_t value.
4    Copyright (C) 1993-1999, 2002-2007, 2009-2011 Free Software Foundation, Inc.
5    This file is part of the GNU C Library.
6    Contributed by Paul Eggert <eggert@twinsun.com>.
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3, or (at your option)
11    any later version.
12
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License along
19    with this program; if not, write to the Free Software Foundation,
20    Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
21
22 /* Define this to have a standalone program to test this implementation of
23    mktime.  */
24 /* #define DEBUG 1 */
25
26 #ifndef _LIBC
27 # include <config.h>
28 #endif
29
30 /* Some of the code in this file assumes that signed integer overflow
31    silently wraps around.  This assumption can't easily be programmed
32    around, nor can it be checked for portably at compile-time or
33    easily eliminated at run-time.
34
35    Define WRAPV to 1 if the assumption is valid.  Otherwise, define it
36    to 0; this forces the use of slower code that, while not guaranteed
37    by the C Standard, works on all production platforms that we know
38    about.  */
39 #ifndef WRAPV
40 # if (__GNUC__ == 4 && 4 <= __GNUC_MINOR__) || 4 < __GNUC__
41 #  pragma GCC optimize ("wrapv")
42 #  define WRAPV 1
43 # else
44 #  define WRAPV 0
45 # endif
46 #endif
47
48 /* Assume that leap seconds are possible, unless told otherwise.
49    If the host has a `zic' command with a `-L leapsecondfilename' option,
50    then it supports leap seconds; otherwise it probably doesn't.  */
51 #ifndef LEAP_SECONDS_POSSIBLE
52 # define LEAP_SECONDS_POSSIBLE 1
53 #endif
54
55 #include <time.h>
56
57 #include <limits.h>
58
59 #include <string.h>             /* For the real memcpy prototype.  */
60
61 #if DEBUG
62 # include <stdio.h>
63 # include <stdlib.h>
64 /* Make it work even if the system's libc has its own mktime routine.  */
65 # undef mktime
66 # define mktime my_mktime
67 #endif /* DEBUG */
68
69 /* Verify a requirement at compile-time (unlike assert, which is runtime).  */
70 #define verify(name, assertion) struct name { char a[(assertion) ? 1 : -1]; }
71
72 /* A signed type that is at least one bit wider than int.  */
73 #if INT_MAX <= LONG_MAX / 2
74 typedef long int long_int;
75 #else
76 typedef long long int long_int;
77 #endif
78 verify (long_int_is_wide_enough, INT_MAX == INT_MAX * (long_int) 2 / 2);
79
80 /* Shift A right by B bits portably, by dividing A by 2**B and
81    truncating towards minus infinity.  A and B should be free of side
82    effects, and B should be in the range 0 <= B <= INT_BITS - 2, where
83    INT_BITS is the number of useful bits in an int.  GNU code can
84    assume that INT_BITS is at least 32.
85
86    ISO C99 says that A >> B is implementation-defined if A < 0.  Some
87    implementations (e.g., UNICOS 9.0 on a Cray Y-MP EL) don't shift
88    right in the usual way when A < 0, so SHR falls back on division if
89    ordinary A >> B doesn't seem to be the usual signed shift.  */
90 #define SHR(a, b)                                               \
91   ((-1 >> 1 == -1                                               \
92     && (long_int) -1 >> 1 == -1                                 \
93     && ((time_t) -1 >> 1 == -1 || ! TYPE_SIGNED (time_t)))      \
94    ? (a) >> (b)                                                 \
95    : (a) / (1 << (b)) - ((a) % (1 << (b)) < 0))
96
97 /* The extra casts in the following macros work around compiler bugs,
98    e.g., in Cray C 5.0.3.0.  */
99
100 /* True if the arithmetic type T is an integer type.  bool counts as
101    an integer.  */
102 #define TYPE_IS_INTEGER(t) ((t) 1.5 == 1)
103
104 /* True if negative values of the signed integer type T use two's
105    complement, or if T is an unsigned integer type.  */
106 #define TYPE_TWOS_COMPLEMENT(t) ((t) ~ (t) 0 == (t) -1)
107
108 /* True if the arithmetic type T is signed.  */
109 #define TYPE_SIGNED(t) (! ((t) 0 < (t) -1))
110
111 /* The maximum and minimum values for the integer type T.  These
112    macros have undefined behavior if T is signed and has padding bits.
113    If this is a problem for you, please let us know how to fix it for
114    your host.  */
115 #define TYPE_MINIMUM(t) \
116   ((t) (! TYPE_SIGNED (t) \
117         ? (t) 0 \
118         : ~ TYPE_MAXIMUM (t)))
119 #define TYPE_MAXIMUM(t) \
120   ((t) (! TYPE_SIGNED (t) \
121         ? (t) -1 \
122         : ((((t) 1 << (sizeof (t) * CHAR_BIT - 2)) - 1) * 2 + 1)))
123
124 #ifndef TIME_T_MIN
125 # define TIME_T_MIN TYPE_MINIMUM (time_t)
126 #endif
127 #ifndef TIME_T_MAX
128 # define TIME_T_MAX TYPE_MAXIMUM (time_t)
129 #endif
130 #define TIME_T_MIDPOINT (SHR (TIME_T_MIN + TIME_T_MAX, 1) + 1)
131
132 verify (time_t_is_integer, TYPE_IS_INTEGER (time_t));
133 verify (twos_complement_arithmetic,
134         (TYPE_TWOS_COMPLEMENT (int)
135          && TYPE_TWOS_COMPLEMENT (long_int)
136          && TYPE_TWOS_COMPLEMENT (time_t)));
137
138 #define EPOCH_YEAR 1970
139 #define TM_YEAR_BASE 1900
140 verify (base_year_is_a_multiple_of_100, TM_YEAR_BASE % 100 == 0);
141
142 /* Return 1 if YEAR + TM_YEAR_BASE is a leap year.  */
143 static inline int
144 leapyear (long_int year)
145 {
146   /* Don't add YEAR to TM_YEAR_BASE, as that might overflow.
147      Also, work even if YEAR is negative.  */
148   return
149     ((year & 3) == 0
150      && (year % 100 != 0
151          || ((year / 100) & 3) == (- (TM_YEAR_BASE / 100) & 3)));
152 }
153
154 /* How many days come before each month (0-12).  */
155 #ifndef _LIBC
156 static
157 #endif
158 const unsigned short int __mon_yday[2][13] =
159   {
160     /* Normal years.  */
161     { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
162     /* Leap years.  */
163     { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
164   };
165
166
167 #ifndef _LIBC
168 /* Portable standalone applications should supply a <time.h> that
169    declares a POSIX-compliant localtime_r, for the benefit of older
170    implementations that lack localtime_r or have a nonstandard one.
171    See the gnulib time_r module for one way to implement this.  */
172 # undef __localtime_r
173 # define __localtime_r localtime_r
174 # define __mktime_internal mktime_internal
175 # include "mktime-internal.h"
176 #endif
177
178 /* Return 1 if the values A and B differ according to the rules for
179    tm_isdst: A and B differ if one is zero and the other positive.  */
180 static int
181 isdst_differ (int a, int b)
182 {
183   return (!a != !b) & (0 <= a) & (0 <= b);
184 }
185
186 /* Return an integer value measuring (YEAR1-YDAY1 HOUR1:MIN1:SEC1) -
187    (YEAR0-YDAY0 HOUR0:MIN0:SEC0) in seconds, assuming that the clocks
188    were not adjusted between the time stamps.
189
190    The YEAR values uses the same numbering as TP->tm_year.  Values
191    need not be in the usual range.  However, YEAR1 must not be less
192    than 2 * INT_MIN or greater than 2 * INT_MAX.
193
194    The result may overflow.  It is the caller's responsibility to
195    detect overflow.  */
196
197 static inline time_t
198 ydhms_diff (long_int year1, long_int yday1, int hour1, int min1, int sec1,
199             int year0, int yday0, int hour0, int min0, int sec0)
200 {
201   verify (C99_integer_division, -1 / 2 == 0);
202
203   /* Compute intervening leap days correctly even if year is negative.
204      Take care to avoid integer overflow here.  */
205   int a4 = SHR (year1, 2) + SHR (TM_YEAR_BASE, 2) - ! (year1 & 3);
206   int b4 = SHR (year0, 2) + SHR (TM_YEAR_BASE, 2) - ! (year0 & 3);
207   int a100 = a4 / 25 - (a4 % 25 < 0);
208   int b100 = b4 / 25 - (b4 % 25 < 0);
209   int a400 = SHR (a100, 2);
210   int b400 = SHR (b100, 2);
211   int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400);
212
213   /* Compute the desired time in time_t precision.  Overflow might
214      occur here.  */
215   time_t tyear1 = year1;
216   time_t years = tyear1 - year0;
217   time_t days = 365 * years + yday1 - yday0 + intervening_leap_days;
218   time_t hours = 24 * days + hour1 - hour0;
219   time_t minutes = 60 * hours + min1 - min0;
220   time_t seconds = 60 * minutes + sec1 - sec0;
221   return seconds;
222 }
223
224 /* Return the average of A and B, even if A + B would overflow.  */
225 static time_t
226 time_t_avg (time_t a, time_t b)
227 {
228   return SHR (a, 1) + SHR (b, 1) + (a & b & 1);
229 }
230
231 /* Return 1 if A + B does not overflow.  If time_t is unsigned and if
232    B's top bit is set, assume that the sum represents A - -B, and
233    return 1 if the subtraction does not wrap around.  */
234 static int
235 time_t_add_ok (time_t a, time_t b)
236 {
237   if (! TYPE_SIGNED (time_t))
238     {
239       time_t sum = a + b;
240       return (sum < a) == (TIME_T_MIDPOINT <= b);
241     }
242   else if (WRAPV)
243     {
244       time_t sum = a + b;
245       return (sum < a) == (b < 0);
246     }
247   else
248     {
249       time_t avg = time_t_avg (a, b);
250       return TIME_T_MIN / 2 <= avg && avg <= TIME_T_MAX / 2;
251     }
252 }
253
254 /* Return 1 if A + B does not overflow.  */
255 static int
256 time_t_int_add_ok (time_t a, int b)
257 {
258   verify (int_no_wider_than_time_t, INT_MAX <= TIME_T_MAX);
259   if (WRAPV)
260     {
261       time_t sum = a + b;
262       return (sum < a) == (b < 0);
263     }
264   else
265     {
266       int a_odd = a & 1;
267       time_t avg = SHR (a, 1) + (SHR (b, 1) + (a_odd & b));
268       return TIME_T_MIN / 2 <= avg && avg <= TIME_T_MAX / 2;
269     }
270 }
271
272 /* Return a time_t value corresponding to (YEAR-YDAY HOUR:MIN:SEC),
273    assuming that *T corresponds to *TP and that no clock adjustments
274    occurred between *TP and the desired time.
275    If TP is null, return a value not equal to *T; this avoids false matches.
276    If overflow occurs, yield the minimal or maximal value, except do not
277    yield a value equal to *T.  */
278 static time_t
279 guess_time_tm (long_int year, long_int yday, int hour, int min, int sec,
280                const time_t *t, const struct tm *tp)
281 {
282   if (tp)
283     {
284       time_t d = ydhms_diff (year, yday, hour, min, sec,
285                              tp->tm_year, tp->tm_yday,
286                              tp->tm_hour, tp->tm_min, tp->tm_sec);
287       if (time_t_add_ok (*t, d))
288         return *t + d;
289     }
290
291   /* Overflow occurred one way or another.  Return the nearest result
292      that is actually in range, except don't report a zero difference
293      if the actual difference is nonzero, as that would cause a false
294      match; and don't oscillate between two values, as that would
295      confuse the spring-forward gap detector.  */
296   return (*t < TIME_T_MIDPOINT
297           ? (*t <= TIME_T_MIN + 1 ? *t + 1 : TIME_T_MIN)
298           : (TIME_T_MAX - 1 <= *t ? *t - 1 : TIME_T_MAX));
299 }
300
301 /* Use CONVERT to convert *T to a broken down time in *TP.
302    If *T is out of range for conversion, adjust it so that
303    it is the nearest in-range value and then convert that.  */
304 static struct tm *
305 ranged_convert (struct tm *(*convert) (const time_t *, struct tm *),
306                 time_t *t, struct tm *tp)
307 {
308   struct tm *r = convert (t, tp);
309
310   if (!r && *t)
311     {
312       time_t bad = *t;
313       time_t ok = 0;
314
315       /* BAD is a known unconvertible time_t, and OK is a known good one.
316          Use binary search to narrow the range between BAD and OK until
317          they differ by 1.  */
318       while (bad != ok + (bad < 0 ? -1 : 1))
319         {
320           time_t mid = *t = time_t_avg (ok, bad);
321           r = convert (t, tp);
322           if (r)
323             ok = mid;
324           else
325             bad = mid;
326         }
327
328       if (!r && ok)
329         {
330           /* The last conversion attempt failed;
331              revert to the most recent successful attempt.  */
332           *t = ok;
333           r = convert (t, tp);
334         }
335     }
336
337   return r;
338 }
339
340
341 /* Convert *TP to a time_t value, inverting
342    the monotonic and mostly-unit-linear conversion function CONVERT.
343    Use *OFFSET to keep track of a guess at the offset of the result,
344    compared to what the result would be for UTC without leap seconds.
345    If *OFFSET's guess is correct, only one CONVERT call is needed.
346    This function is external because it is used also by timegm.c.  */
347 time_t
348 __mktime_internal (struct tm *tp,
349                    struct tm *(*convert) (const time_t *, struct tm *),
350                    time_t *offset)
351 {
352   time_t t, gt, t0, t1, t2;
353   struct tm tm;
354
355   /* The maximum number of probes (calls to CONVERT) should be enough
356      to handle any combinations of time zone rule changes, solar time,
357      leap seconds, and oscillations around a spring-forward gap.
358      POSIX.1 prohibits leap seconds, but some hosts have them anyway.  */
359   int remaining_probes = 6;
360
361   /* Time requested.  Copy it in case CONVERT modifies *TP; this can
362      occur if TP is localtime's returned value and CONVERT is localtime.  */
363   int sec = tp->tm_sec;
364   int min = tp->tm_min;
365   int hour = tp->tm_hour;
366   int mday = tp->tm_mday;
367   int mon = tp->tm_mon;
368   int year_requested = tp->tm_year;
369   int isdst = tp->tm_isdst;
370
371   /* 1 if the previous probe was DST.  */
372   int dst2;
373
374   /* Ensure that mon is in range, and set year accordingly.  */
375   int mon_remainder = mon % 12;
376   int negative_mon_remainder = mon_remainder < 0;
377   int mon_years = mon / 12 - negative_mon_remainder;
378   long_int lyear_requested = year_requested;
379   long_int year = lyear_requested + mon_years;
380
381   /* The other values need not be in range:
382      the remaining code handles minor overflows correctly,
383      assuming int and time_t arithmetic wraps around.
384      Major overflows are caught at the end.  */
385
386   /* Calculate day of year from year, month, and day of month.
387      The result need not be in range.  */
388   int mon_yday = ((__mon_yday[leapyear (year)]
389                    [mon_remainder + 12 * negative_mon_remainder])
390                   - 1);
391   long_int lmday = mday;
392   long_int yday = mon_yday + lmday;
393
394   time_t guessed_offset = *offset;
395
396   int sec_requested = sec;
397
398   if (LEAP_SECONDS_POSSIBLE)
399     {
400       /* Handle out-of-range seconds specially,
401          since ydhms_tm_diff assumes every minute has 60 seconds.  */
402       if (sec < 0)
403         sec = 0;
404       if (59 < sec)
405         sec = 59;
406     }
407
408   /* Invert CONVERT by probing.  First assume the same offset as last
409      time.  */
410
411   t0 = ydhms_diff (year, yday, hour, min, sec,
412                    EPOCH_YEAR - TM_YEAR_BASE, 0, 0, 0, - guessed_offset);
413
414   if (TIME_T_MAX / INT_MAX / 366 / 24 / 60 / 60 < 3)
415     {
416       /* time_t isn't large enough to rule out overflows, so check
417          for major overflows.  A gross check suffices, since if t0
418          has overflowed, it is off by a multiple of TIME_T_MAX -
419          TIME_T_MIN + 1.  So ignore any component of the difference
420          that is bounded by a small value.  */
421
422       /* Approximate log base 2 of the number of time units per
423          biennium.  A biennium is 2 years; use this unit instead of
424          years to avoid integer overflow.  For example, 2 average
425          Gregorian years are 2 * 365.2425 * 24 * 60 * 60 seconds,
426          which is 63113904 seconds, and rint (log2 (63113904)) is
427          26.  */
428       int ALOG2_SECONDS_PER_BIENNIUM = 26;
429       int ALOG2_MINUTES_PER_BIENNIUM = 20;
430       int ALOG2_HOURS_PER_BIENNIUM = 14;
431       int ALOG2_DAYS_PER_BIENNIUM = 10;
432       int LOG2_YEARS_PER_BIENNIUM = 1;
433
434       int approx_requested_biennia =
435         (SHR (year_requested, LOG2_YEARS_PER_BIENNIUM)
436          - SHR (EPOCH_YEAR - TM_YEAR_BASE, LOG2_YEARS_PER_BIENNIUM)
437          + SHR (mday, ALOG2_DAYS_PER_BIENNIUM)
438          + SHR (hour, ALOG2_HOURS_PER_BIENNIUM)
439          + SHR (min, ALOG2_MINUTES_PER_BIENNIUM)
440          + (LEAP_SECONDS_POSSIBLE
441             ? 0
442             : SHR (sec, ALOG2_SECONDS_PER_BIENNIUM)));
443
444       int approx_biennia = SHR (t0, ALOG2_SECONDS_PER_BIENNIUM);
445       int diff = approx_biennia - approx_requested_biennia;
446       int abs_diff = diff < 0 ? -1 - diff : diff;
447
448       /* IRIX 4.0.5 cc miscalculates TIME_T_MIN / 3: it erroneously
449          gives a positive value of 715827882.  Setting a variable
450          first then doing math on it seems to work.
451          (ghazi@caip.rutgers.edu) */
452       time_t time_t_max = TIME_T_MAX;
453       time_t time_t_min = TIME_T_MIN;
454       time_t overflow_threshold =
455         (time_t_max / 3 - time_t_min / 3) >> ALOG2_SECONDS_PER_BIENNIUM;
456
457       if (overflow_threshold < abs_diff)
458         {
459           /* Overflow occurred.  Try repairing it; this might work if
460              the time zone offset is enough to undo the overflow.  */
461           time_t repaired_t0 = -1 - t0;
462           approx_biennia = SHR (repaired_t0, ALOG2_SECONDS_PER_BIENNIUM);
463           diff = approx_biennia - approx_requested_biennia;
464           abs_diff = diff < 0 ? -1 - diff : diff;
465           if (overflow_threshold < abs_diff)
466             return -1;
467           guessed_offset += repaired_t0 - t0;
468           t0 = repaired_t0;
469         }
470     }
471
472   /* Repeatedly use the error to improve the guess.  */
473
474   for (t = t1 = t2 = t0, dst2 = 0;
475        (gt = guess_time_tm (year, yday, hour, min, sec, &t,
476                             ranged_convert (convert, &t, &tm)),
477         t != gt);
478        t1 = t2, t2 = t, t = gt, dst2 = tm.tm_isdst != 0)
479     if (t == t1 && t != t2
480         && (tm.tm_isdst < 0
481             || (isdst < 0
482                 ? dst2 <= (tm.tm_isdst != 0)
483                 : (isdst != 0) != (tm.tm_isdst != 0))))
484       /* We can't possibly find a match, as we are oscillating
485          between two values.  The requested time probably falls
486          within a spring-forward gap of size GT - T.  Follow the common
487          practice in this case, which is to return a time that is GT - T
488          away from the requested time, preferring a time whose
489          tm_isdst differs from the requested value.  (If no tm_isdst
490          was requested and only one of the two values has a nonzero
491          tm_isdst, prefer that value.)  In practice, this is more
492          useful than returning -1.  */
493       goto offset_found;
494     else if (--remaining_probes == 0)
495       return -1;
496
497   /* We have a match.  Check whether tm.tm_isdst has the requested
498      value, if any.  */
499   if (isdst_differ (isdst, tm.tm_isdst))
500     {
501       /* tm.tm_isdst has the wrong value.  Look for a neighboring
502          time with the right value, and use its UTC offset.
503
504          Heuristic: probe the adjacent timestamps in both directions,
505          looking for the desired isdst.  This should work for all real
506          time zone histories in the tz database.  */
507
508       /* Distance between probes when looking for a DST boundary.  In
509          tzdata2003a, the shortest period of DST is 601200 seconds
510          (e.g., America/Recife starting 2000-10-08 01:00), and the
511          shortest period of non-DST surrounded by DST is 694800
512          seconds (Africa/Tunis starting 1943-04-17 01:00).  Use the
513          minimum of these two values, so we don't miss these short
514          periods when probing.  */
515       int stride = 601200;
516
517       /* The longest period of DST in tzdata2003a is 536454000 seconds
518          (e.g., America/Jujuy starting 1946-10-01 01:00).  The longest
519          period of non-DST is much longer, but it makes no real sense
520          to search for more than a year of non-DST, so use the DST
521          max.  */
522       int duration_max = 536454000;
523
524       /* Search in both directions, so the maximum distance is half
525          the duration; add the stride to avoid off-by-1 problems.  */
526       int delta_bound = duration_max / 2 + stride;
527
528       int delta, direction;
529
530       for (delta = stride; delta < delta_bound; delta += stride)
531         for (direction = -1; direction <= 1; direction += 2)
532           if (time_t_int_add_ok (t, delta * direction))
533             {
534               time_t ot = t + delta * direction;
535               struct tm otm;
536               ranged_convert (convert, &ot, &otm);
537               if (! isdst_differ (isdst, otm.tm_isdst))
538                 {
539                   /* We found the desired tm_isdst.
540                      Extrapolate back to the desired time.  */
541                   t = guess_time_tm (year, yday, hour, min, sec, &ot, &otm);
542                   ranged_convert (convert, &t, &tm);
543                   goto offset_found;
544                 }
545             }
546     }
547
548  offset_found:
549   *offset = guessed_offset + t - t0;
550
551   if (LEAP_SECONDS_POSSIBLE && sec_requested != tm.tm_sec)
552     {
553       /* Adjust time to reflect the tm_sec requested, not the normalized value.
554          Also, repair any damage from a false match due to a leap second.  */
555       int sec_adjustment = (sec == 0 && tm.tm_sec == 60) - sec;
556       if (! time_t_int_add_ok (t, sec_requested))
557         return -1;
558       t1 = t + sec_requested;
559       if (! time_t_int_add_ok (t1, sec_adjustment))
560         return -1;
561       t2 = t1 + sec_adjustment;
562       if (! convert (&t2, &tm))
563         return -1;
564       t = t2;
565     }
566
567   *tp = tm;
568   return t;
569 }
570
571
572 /* FIXME: This should use a signed type wide enough to hold any UTC
573    offset in seconds.  'int' should be good enough for GNU code.  We
574    can't fix this unilaterally though, as other modules invoke
575    __mktime_internal.  */
576 static time_t localtime_offset;
577
578 /* Convert *TP to a time_t value.  */
579 time_t
580 mktime (struct tm *tp)
581 {
582 #ifdef _LIBC
583   /* POSIX.1 8.1.1 requires that whenever mktime() is called, the
584      time zone names contained in the external variable `tzname' shall
585      be set as if the tzset() function had been called.  */
586   __tzset ();
587 #endif
588
589   return __mktime_internal (tp, __localtime_r, &localtime_offset);
590 }
591
592 #ifdef weak_alias
593 weak_alias (mktime, timelocal)
594 #endif
595
596 #ifdef _LIBC
597 libc_hidden_def (mktime)
598 libc_hidden_weak (timelocal)
599 #endif
600 \f
601 #if DEBUG
602
603 static int
604 not_equal_tm (const struct tm *a, const struct tm *b)
605 {
606   return ((a->tm_sec ^ b->tm_sec)
607           | (a->tm_min ^ b->tm_min)
608           | (a->tm_hour ^ b->tm_hour)
609           | (a->tm_mday ^ b->tm_mday)
610           | (a->tm_mon ^ b->tm_mon)
611           | (a->tm_year ^ b->tm_year)
612           | (a->tm_yday ^ b->tm_yday)
613           | isdst_differ (a->tm_isdst, b->tm_isdst));
614 }
615
616 static void
617 print_tm (const struct tm *tp)
618 {
619   if (tp)
620     printf ("%04d-%02d-%02d %02d:%02d:%02d yday %03d wday %d isdst %d",
621             tp->tm_year + TM_YEAR_BASE, tp->tm_mon + 1, tp->tm_mday,
622             tp->tm_hour, tp->tm_min, tp->tm_sec,
623             tp->tm_yday, tp->tm_wday, tp->tm_isdst);
624   else
625     printf ("0");
626 }
627
628 static int
629 check_result (time_t tk, struct tm tmk, time_t tl, const struct tm *lt)
630 {
631   if (tk != tl || !lt || not_equal_tm (&tmk, lt))
632     {
633       printf ("mktime (");
634       print_tm (lt);
635       printf (")\nyields (");
636       print_tm (&tmk);
637       printf (") == %ld, should be %ld\n", (long int) tk, (long int) tl);
638       return 1;
639     }
640
641   return 0;
642 }
643
644 int
645 main (int argc, char **argv)
646 {
647   int status = 0;
648   struct tm tm, tmk, tml;
649   struct tm *lt;
650   time_t tk, tl, tl1;
651   char trailer;
652
653   if ((argc == 3 || argc == 4)
654       && (sscanf (argv[1], "%d-%d-%d%c",
655                   &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &trailer)
656           == 3)
657       && (sscanf (argv[2], "%d:%d:%d%c",
658                   &tm.tm_hour, &tm.tm_min, &tm.tm_sec, &trailer)
659           == 3))
660     {
661       tm.tm_year -= TM_YEAR_BASE;
662       tm.tm_mon--;
663       tm.tm_isdst = argc == 3 ? -1 : atoi (argv[3]);
664       tmk = tm;
665       tl = mktime (&tmk);
666       lt = localtime (&tl);
667       if (lt)
668         {
669           tml = *lt;
670           lt = &tml;
671         }
672       printf ("mktime returns %ld == ", (long int) tl);
673       print_tm (&tmk);
674       printf ("\n");
675       status = check_result (tl, tmk, tl, lt);
676     }
677   else if (argc == 4 || (argc == 5 && strcmp (argv[4], "-") == 0))
678     {
679       time_t from = atol (argv[1]);
680       time_t by = atol (argv[2]);
681       time_t to = atol (argv[3]);
682
683       if (argc == 4)
684         for (tl = from; by < 0 ? to <= tl : tl <= to; tl = tl1)
685           {
686             lt = localtime (&tl);
687             if (lt)
688               {
689                 tmk = tml = *lt;
690                 tk = mktime (&tmk);
691                 status |= check_result (tk, tmk, tl, &tml);
692               }
693             else
694               {
695                 printf ("localtime (%ld) yields 0\n", (long int) tl);
696                 status = 1;
697               }
698             tl1 = tl + by;
699             if ((tl1 < tl) != (by < 0))
700               break;
701           }
702       else
703         for (tl = from; by < 0 ? to <= tl : tl <= to; tl = tl1)
704           {
705             /* Null benchmark.  */
706             lt = localtime (&tl);
707             if (lt)
708               {
709                 tmk = tml = *lt;
710                 tk = tl;
711                 status |= check_result (tk, tmk, tl, &tml);
712               }
713             else
714               {
715                 printf ("localtime (%ld) yields 0\n", (long int) tl);
716                 status = 1;
717               }
718             tl1 = tl + by;
719             if ((tl1 < tl) != (by < 0))
720               break;
721           }
722     }
723   else
724     printf ("Usage:\
725 \t%s YYYY-MM-DD HH:MM:SS [ISDST] # Test given time.\n\
726 \t%s FROM BY TO # Test values FROM, FROM+BY, ..., TO.\n\
727 \t%s FROM BY TO - # Do not test those values (for benchmark).\n",
728             argv[0], argv[0], argv[0]);
729
730   return status;
731 }
732
733 #endif /* DEBUG */
734 \f
735 /*
736 Local Variables:
737 compile-command: "gcc -DDEBUG -I. -Wall -W -O2 -g mktime.c -o mktime"
738 End:
739 */