Sat Apr 20 17:07:17 1996 Ulrich Drepper <drepper@cygnus.com>
[kopensolaris-gnu/glibc.git] / time / tzfile.c
index 8ee4896..e78a05e 100644 (file)
@@ -54,10 +54,27 @@ static char *zone_names = NULL;
 static size_t num_leaps;
 static struct leap *leaps = NULL;
 
-#define        uc2ul(x)        _uc2ul((unsigned char *) (x))
-#define        _uc2ul(x)                                                             \
-  ((x)[3] + ((x)[2] << CHAR_BIT) + ((x)[1] << (2 * CHAR_BIT)) +                      \
-   ((x)[0] << (3 * CHAR_BIT)))
+#include <endian.h>
+
+/* Decode the four bytes at PTR as a signed integer in network byte order.  */
+static inline int
+decode (const void *ptr)
+{
+  if ((BYTE_ORDER == BIG_ENDIAN) && sizeof (int) == 4)
+    return *(const int *) ptr;
+  else
+    {
+      const unsigned char *p = ptr;
+      int result = *p & (1 << (CHAR_BIT - 1)) ? ~0 : 0;
+
+      result = (result << 8) | *p++;
+      result = (result << 8) | *p++;
+      result = (result << 8) | *p++;
+      result = (result << 8) | *p++;
+
+      return result;
+    }
+}
 
 void
 DEFUN(__tzfile_read, (file), CONST char *file)
@@ -107,12 +124,12 @@ DEFUN(__tzfile_read, (file), CONST char *file)
   if (fread((PTR) &tzhead, sizeof(tzhead), 1, f) != 1)
     goto lose;
 
-  num_transitions = (size_t) uc2ul(tzhead.tzh_timecnt);
-  num_types = (size_t) uc2ul (tzhead.tzh_typecnt);
-  chars = (size_t) uc2ul (tzhead.tzh_charcnt);
-  num_leaps = (size_t) uc2ul (tzhead.tzh_leapcnt);
-  num_isstd = (size_t) uc2ul (tzhead.tzh_ttisstdcnt);
-  num_isgmt = (size_t) uc2ul (tzhead.tzh_ttisgmtcnt);
+  num_transitions = (size_t) decode (tzhead.tzh_timecnt);
+  num_types = (size_t) decode (tzhead.tzh_typecnt);
+  chars = (size_t) decode (tzhead.tzh_charcnt);
+  num_leaps = (size_t) decode (tzhead.tzh_leapcnt);
+  num_isstd = (size_t) decode (tzhead.tzh_ttisstdcnt);
+  num_isgmt = (size_t) decode (tzhead.tzh_ttisgmtcnt);
 
   if (num_transitions > 0)
     {
@@ -142,13 +159,23 @@ DEFUN(__tzfile_read, (file), CONST char *file)
        goto lose;
     }
 
-  if (fread((PTR) transitions, sizeof(time_t),
-           num_transitions, f) != num_transitions ||
+  if (sizeof (time_t) < 4)
+      abort ();
+
+  if (fread((PTR) transitions, 4, num_transitions, f) != num_transitions ||
       fread((PTR) type_idxs, 1, num_transitions, f) != num_transitions)
     goto lose;
 
-  for (i = 0; i < num_transitions; ++i)
-    transitions[i] = uc2ul (&transitions[i]);
+  if (BYTE_ORDER != BIG_ENDIAN || sizeof (time_t) != 4)
+    {
+      /* Decode the transition times, stored as 4-byte integers in
+        network (big-endian) byte order.  We work from the end of
+        the array so as not to clobber the next element to be
+        processed when sizeof (time_t) > 4.  */
+      i = num_transitions;
+      while (i-- > 0)
+       transitions[i] = decode ((char *) transitions + i*4);
+    }
 
   for (i = 0; i < num_types; ++i)
     {
@@ -157,7 +184,7 @@ DEFUN(__tzfile_read, (file), CONST char *file)
          fread((PTR) &types[i].isdst, 1, 1, f) != 1 ||
          fread((PTR) &types[i].idx, 1, 1, f) != 1)
        goto lose;
-      types[i].offset = (long int) uc2ul(x);
+      types[i].offset = (long int) decode (x);
     }
 
   if (fread((PTR) zone_names, 1, chars, f) != chars)
@@ -168,10 +195,10 @@ DEFUN(__tzfile_read, (file), CONST char *file)
       unsigned char x[4];
       if (fread((PTR) x, 1, sizeof(x), f) != sizeof(x))
        goto lose;
-      leaps[i].transition = (time_t) uc2ul(x);
+      leaps[i].transition = (time_t) decode (x);
       if (fread((PTR) x, 1, sizeof(x), f) != sizeof(x))
        goto lose;
-      leaps[i].change = (long int) uc2ul(x);
+      leaps[i].change = (long int) decode (x);
     }
 
   for (i = 0; i < num_isstd; ++i)
@@ -246,7 +273,7 @@ DEFUN(__tzfile_default, (std, dst, stdoff, dstoff),
   /* Find the standard and daylight time offsets used by the rule file.
      We choose the offsets in the types of each flavor that are
      transitioned to earliest in time.  */
-  rule_dstoff = 0;
+  rule_stdoff = rule_dstoff = 0;
   for (i = 0; i < num_transitions; ++i)
     {
       if (!rule_stdoff && !types[type_idxs[i]].isdst)