~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to gnulib/mktime.c

  • Committer: Brian Aker
  • Date: 2009-04-27 14:36:40 UTC
  • Revision ID: brian@gaz-20090427143640-f6zjmtt9vm55qgm2
Patch on show processlist from  davi@apache.org

Show diffs side-by-side

added added

removed removed

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