snippet/warn-on-use: Fix indentation.
[gnulib.git] / lib / mktime.c
index 6eb9bfc..cba2b8b 100644 (file)
 # include <stdio.h>
 # include <stdlib.h>
 /* Make it work even if the system's libc has its own mktime routine.  */
+# undef mktime
 # define mktime my_mktime
 #endif /* DEBUG */
 
+/* Verify a requirement at compile-time (unlike assert, which is runtime).  */
+#define verify(name, assertion) struct name { char a[(assertion) ? 1 : -1]; }
+
 /* A signed type that is at least one bit wider than int.  */
 #if INT_MAX <= LONG_MAX / 2
 typedef long int long_int;
 #else
 typedef long long int long_int;
 #endif
+verify (long_int_is_wide_enough, INT_MAX == INT_MAX * (long_int) 2 / 2);
 
 /* Shift A right by B bits portably, by dividing A by 2**B and
    truncating towards minus infinity.  A and B should be free of side
@@ -112,7 +117,7 @@ typedef long long int long_int;
 #define TYPE_MAXIMUM(t) \
   ((t) (! TYPE_SIGNED (t) \
         ? (t) -1 \
-        : (((((t) 1 << (sizeof (t) * CHAR_BIT - 2)) - 1) << 1) + 1)))
+        : ((((t) 1 << (sizeof (t) * CHAR_BIT - 2)) - 1) * 2 + 1)))
 
 #ifndef TIME_T_MIN
 # define TIME_T_MIN TYPE_MINIMUM (time_t)
@@ -122,9 +127,6 @@ typedef long long int long_int;
 #endif
 #define TIME_T_MIDPOINT (SHR (TIME_T_MIN + TIME_T_MAX, 1) + 1)
 
-/* Verify a requirement at compile-time (unlike assert, which is runtime).  */
-#define verify(name, assertion) struct name { char a[(assertion) ? 1 : -1]; }
-
 verify (time_t_is_integer, TYPE_IS_INTEGER (time_t));
 verify (twos_complement_arithmetic,
         (TYPE_TWOS_COMPLEMENT (int)
@@ -171,6 +173,14 @@ const unsigned short int __mon_yday[2][13] =
 # include "mktime-internal.h"
 #endif
 
+/* Return 1 if the values A and B differ according to the rules for
+   tm_isdst: A and B differ if one is zero and the other positive.  */
+static int
+isdst_differ (int a, int b)
+{
+  return (!a != !b) & (0 <= a) & (0 <= b);
+}
+
 /* Return an integer value measuring (YEAR1-YDAY1 HOUR1:MIN1:SEC1) -
    (YEAR0-YDAY0 HOUR0:MIN0:SEC0) in seconds, assuming that the clocks
    were not adjusted between the time stamps.
@@ -187,8 +197,6 @@ ydhms_diff (long_int year1, long_int yday1, int hour1, int min1, int sec1,
             int year0, int yday0, int hour0, int min0, int sec0)
 {
   verify (C99_integer_division, -1 / 2 == 0);
-  verify (long_int_year_and_yday_are_wide_enough,
-          INT_MAX == INT_MAX * (long_int) 2 / 2);
 
   /* Compute intervening leap days correctly even if year is negative.
      Take care to avoid integer overflow here.  */
@@ -356,9 +364,7 @@ __mktime_internal (struct tm *tp,
   int mday = tp->tm_mday;
   int mon = tp->tm_mon;
   int year_requested = tp->tm_year;
-  /* Normalize the value.  */
-  int isdst = ((tp->tm_isdst >> (8 * sizeof (tp->tm_isdst) - 1))
-               | (tp->tm_isdst != 0));
+  int isdst = tp->tm_isdst;
 
   /* 1 if the previous probe was DST.  */
   int dst2;
@@ -488,7 +494,7 @@ __mktime_internal (struct tm *tp,
 
   /* We have a match.  Check whether tm.tm_isdst has the requested
      value, if any.  */
-  if (isdst != tm.tm_isdst && 0 <= isdst && 0 <= tm.tm_isdst)
+  if (isdst_differ (isdst, tm.tm_isdst))
     {
       /* tm.tm_isdst has the wrong value.  Look for a neighboring
          time with the right value, and use its UTC offset.
@@ -526,7 +532,7 @@ __mktime_internal (struct tm *tp,
               time_t ot = t + delta * direction;
               struct tm otm;
               ranged_convert (convert, &ot, &otm);
-              if (otm.tm_isdst == isdst)
+              if (! isdst_differ (isdst, otm.tm_isdst))
                 {
                   /* We found the desired tm_isdst.
                      Extrapolate back to the desired time.  */
@@ -602,7 +608,7 @@ not_equal_tm (const struct tm *a, const struct tm *b)
           | (a->tm_mon ^ b->tm_mon)
           | (a->tm_year ^ b->tm_year)
           | (a->tm_yday ^ b->tm_yday)
-          | (a->tm_isdst ^ b->tm_isdst));
+          | isdst_differ (a->tm_isdst, b->tm_isdst));
 }
 
 static void
@@ -726,6 +732,6 @@ main (int argc, char **argv)
 \f
 /*
 Local Variables:
-compile-command: "gcc -DDEBUG -Wall -W -O2 -g mktime.c -o mktime"
+compile-command: "gcc -DDEBUG -I. -Wall -W -O2 -g mktime.c -o mktime"
 End:
 */