Initial revision
authorroland <roland>
Tue, 11 Feb 1992 00:14:13 +0000 (00:14 +0000)
committerroland <roland>
Tue, 11 Feb 1992 00:14:13 +0000 (00:14 +0000)
time/tzfile.c [new file with mode: 0644]

diff --git a/time/tzfile.c b/time/tzfile.c
new file mode 100644 (file)
index 0000000..2f4a51b
--- /dev/null
@@ -0,0 +1,211 @@
+/* Copyright (C) 1991 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#include <ansidecl.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <time.h>
+#include <string.h>
+#include <limits.h>
+
+#define        NOID
+#include <tzfile.h>
+
+int __use_tzfile = 0;
+
+struct ttinfo
+  {
+    long int offset;           /* Seconds east of GMT.  */
+    unsigned char isdst;       /* Used to set tm_isdst.  */
+    unsigned char idx;         /* Index into `zone_names'.  */
+    unsigned int isstd:1;      /* Transition times are standard time.  */
+  };
+
+struct leap
+  {
+    time_t transition;
+    long int change;
+  };
+
+static size_t num_transitions;
+static time_t *transitions = NULL;
+static unsigned char *type_idxs = NULL;
+static size_t num_types;
+static struct ttinfo *types = NULL;
+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)))
+
+void
+DEFUN(__tzfile_read, (file), CONST char *file)
+{
+  size_t num_isstd;
+  register FILE *f;
+  struct tzhead tzhead;
+  size_t chars;
+  register size_t i;
+
+  __use_tzfile = 0;
+
+  if (transitions != NULL)
+    free((PTR) transitions);
+  transitions = NULL;
+  if (type_idxs != NULL)
+    free((PTR) type_idxs);
+  type_idxs = NULL;
+  if (types != NULL)
+    free((PTR) types);
+  types = NULL;
+  if (zone_names != NULL)
+    free((PTR) zone_names);
+  zone_names = NULL;
+  if (leaps != NULL)
+    free((PTR) leaps);
+  leaps = NULL;
+
+  if (file == NULL || *file == '\0')
+    file = TZDEFAULT;
+
+  if (*file != '/')
+    {
+      static CONST char tzdir[] = TZDIR;
+      register CONST unsigned int len = strlen(file) + 1;
+      char *new = (char *) __alloca(sizeof(tzdir) + len);
+      memcpy(new, tzdir, sizeof(tzdir) - 1);
+      new[sizeof(tzdir) - 1] = '/';
+      memcpy(&new[sizeof(tzdir)], file, len);
+      file = new;
+    }
+
+  f = fopen(file, "r");
+  if (f == NULL)
+    return;
+
+  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);
+#if 0
+  num_isstd = (size_t) uc2ul(tzhead.tzh_ttisstdcnt);
+#else
+  num_isstd = 0;
+#endif
+
+  transitions = (time_t *) malloc(num_transitions * sizeof(time_t));
+  if (transitions == NULL)
+    goto lose;
+  type_idxs = (unsigned char *) malloc(num_transitions);
+  if (type_idxs == NULL)
+    goto lose;
+  types = (struct ttinfo *) malloc(num_types * sizeof(struct ttinfo));
+  if (types == NULL)
+    goto lose;
+  zone_names = (char *) malloc(chars);
+  if (zone_names == NULL)
+    goto lose;
+  if (num_leaps != 0)
+    {
+      leaps = (struct leap *) malloc(num_leaps * sizeof(struct leap));
+      if (leaps == NULL)
+       goto lose;
+    }
+
+  if (fread((PTR) transitions, sizeof(time_t),
+           num_transitions, f) != num_transitions ||
+      fread((PTR) type_idxs, 1, num_transitions, f) != num_transitions)
+    goto lose;
+
+  for (i = 0; i < num_types; ++i)
+    {
+      unsigned char x[4];
+      if (fread((PTR) x, 1, 4, f) != 4 ||
+         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);
+    }
+
+  if (fread((PTR) zone_names, 1, chars, f) != chars)
+    goto lose;
+
+  for (i = 0; i < num_leaps; ++i)
+    {
+      unsigned char x[4];
+      if (fread((PTR) x, 1, sizeof(x), f) != sizeof(x))
+       goto lose;
+      leaps[i].transition = (time_t) uc2ul(x);
+      if (fread((PTR) x, 1, sizeof(x), f) != sizeof(x))
+       goto lose;
+      leaps[i].change = (long int) uc2ul(x);
+    }
+
+  for (i = 0; i < num_isstd; ++i)
+    {
+      char c = getc(f);
+      if (c == EOF)
+       goto lose;
+      types[i].isstd = c != 0;
+    }
+  while (i < num_types)
+    types[i++].isstd = 0;
+
+  (void) fclose(f);
+  __use_tzfile = 1;
+  return;
+
+ lose:;
+  (void) fclose(f);
+}
+
+
+int
+DEFUN(__tzfile_compute, (timer, tm), time_t timer AND struct tm tm)
+{
+  struct ttinfo *info;
+  register size_t i;
+
+  i = 0;
+  while (i < num_transitions &&
+        (timer >= transitions[i] && timer < transitions[i + 1]))
+    ++i;
+  if (i == num_transitions)
+    i = 0;
+
+  info = &types[type_idxs[i]];
+  __daylight = info->isdst != 0;
+  __timezone = info->offset;
+  __tzname[0] = &zone_names[types[0].idx];
+  if (num_types > 0)
+    __tzname[1] = &zone_names[types[1].idx];
+
+  i = num_leaps;
+  do
+    if (i-- == 0)
+      return 1;
+  while (timer < leaps[i].transition);
+  __timezone += leaps[i].change;
+  return 1;
+}