New module 'strptime'. Initial fixes.
[gnulib.git] / lib / mktime.c
index 9a92cb0..ded3295 100644 (file)
@@ -1,8 +1,7 @@
 /* Convert a `struct tm' to a time_t value.
-   Copyright (C) 1993-1999, 2002, 2003, 2004, 2005 Free Software Foundation,
-   Inc.
+   Copyright (C) 1993-1999, 2002-2005, 2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
-   Contributed by Paul Eggert (eggert@twinsun.com).
+   Contributed by Paul Eggert <eggert@twinsun.com>.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -16,7 +15,7 @@
 
    You should have received a copy of the GNU General Public License along
    with this program; if not, write to the Free Software Foundation,
-   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
 
 /* Define this to have a standalone program to test this implementation of
    mktime.  */
 
 #include <limits.h>
 
+#include <string.h>            /* For the real memcpy prototype.  */
+
 #if DEBUG
 # include <stdio.h>
 # include <stdlib.h>
-# include <string.h>
 /* Make it work even if the system's libc has its own mktime routine.  */
 # define mktime my_mktime
 #endif /* DEBUG */
    an integer.  */
 #define TYPE_IS_INTEGER(t) ((t) 1.5 == 1)
 
-/* True if negative values of the integer type T use twos complement
-   representation.  */
-#define TYPE_TWOS_COMPLEMENT(t) ((t) - (t) 1 == (t) ((t) ~ (t) 1 + (t) 1))
+/* True if negative values of the signed integer type T use two's
+   complement, ones' complement, or signed magnitude representation,
+   respectively.  Much GNU code assumes two's complement, but some
+   people like to be portable to all possible C hosts.  */
+#define TYPE_TWOS_COMPLEMENT(t) ((t) ~ (t) 0 == (t) -1)
+#define TYPE_ONES_COMPLEMENT(t) ((t) ~ (t) 0 == 0)
+#define TYPE_SIGNED_MAGNITUDE(t) ((t) ~ (t) 0 < (t) -1)
 
 /* True if the arithmetic type T is signed.  */
 #define TYPE_SIGNED(t) (! ((t) 0 < (t) -1))
 
 /* The maximum and minimum values for the integer type T.  These
-   macros have undefined behavior if T is signed and has padding bits
-   (i.e., bits that do not contribute to the value), or if T uses
-   signed-magnitude representation.  If this is a problem for you,
-   please let us know how to fix it for your host.  */
-#define TYPE_MINIMUM(t) ((t) (TYPE_SIGNED (t) \
-                             ? ~ (t) 0 << (sizeof (t) * CHAR_BIT - 1) : (t) 0))
-#define TYPE_MAXIMUM(t) ((t) (~ (t) 0 - TYPE_MINIMUM (t)))
+   macros have undefined behavior if T is signed and has padding bits.
+   If this is a problem for you, please let us know how to fix it for
+   your host.  */
+#define TYPE_MINIMUM(t) \
+  ((t) (! TYPE_SIGNED (t) \
+       ? (t) 0 \
+       : TYPE_SIGNED_MAGNITUDE (t) \
+       ? ~ (t) 0 \
+       : ~ (t) 0 << (sizeof (t) * CHAR_BIT - 1)))
+#define TYPE_MAXIMUM(t) \
+  ((t) (! TYPE_SIGNED (t) \
+       ? (t) -1 \
+       : ~ (~ (t) 0 << (sizeof (t) * CHAR_BIT - 1))))
 
 #ifndef TIME_T_MIN
 # define TIME_T_MIN TYPE_MINIMUM (time_t)
@@ -205,10 +215,11 @@ guess_time_tm (long int year, long int yday, int hour, int min, int sec,
   /* Overflow occurred one way or another.  Return the nearest result
      that is actually in range, except don't report a zero difference
      if the actual difference is nonzero, as that would cause a false
-     match.  */
+     match; and don't oscillate between two values, as that would
+     confuse the spring-forward gap detector.  */
   return (*t < TIME_T_MIDPOINT
-         ? TIME_T_MIN + (*t == TIME_T_MIN)
-         : TIME_T_MAX - (*t == TIME_T_MAX));
+         ? (*t <= TIME_T_MIN + 1 ? *t + 1 : TIME_T_MIN)
+         : (TIME_T_MAX - 1 <= *t ? *t - 1 : TIME_T_MAX));
 }
 
 /* Use CONVERT to convert *T to a broken down time in *TP.
@@ -218,13 +229,12 @@ static struct tm *
 ranged_convert (struct tm *(*convert) (const time_t *, struct tm *),
                time_t *t, struct tm *tp)
 {
-  struct tm *r;
+  struct tm *r = convert (t, tp);
 
-  if (! (r = (*convert) (t, tp)) && *t)
+  if (!r && *t)
     {
       time_t bad = *t;
       time_t ok = 0;
-      struct tm tm;
 
       /* BAD is a known unconvertible time_t, and OK is a known good one.
         Use binary search to narrow the range between BAD and OK until
@@ -234,11 +244,9 @@ ranged_convert (struct tm *(*convert) (const time_t *, struct tm *),
          time_t mid = *t = (bad < 0
                             ? bad + ((ok - bad) >> 1)
                             : ok + ((bad - ok) >> 1));
-         if ((r = (*convert) (t, tp)))
-           {
-             tm = *r;
-             ok = mid;
-           }
+         r = convert (t, tp);
+         if (r)
+           ok = mid;
          else
            bad = mid;
        }
@@ -248,8 +256,7 @@ ranged_convert (struct tm *(*convert) (const time_t *, struct tm *),
          /* The last conversion attempt failed;
             revert to the most recent successful attempt.  */
          *t = ok;
-         *tp = tm;
-         r = tp;
+         r = convert (t, tp);
        }
     }
 
@@ -478,7 +485,7 @@ __mktime_internal (struct tm *tp,
       t2 = t1 + sec_adjustment;
       if (((t1 < t) != (sec_requested < 0))
          | ((t2 < t1) != (sec_adjustment < 0))
-         | ! (*convert) (&t2, &tm))
+         | ! convert (&t2, &tm))
        return -1;
       t = t2;
     }