-/* Copyright (C) 1991 Free Software Foundation, Inc.
+/* Copyright (C) 1991, 1992, 1993 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
#define NOID
#include <tzfile.h>
+#ifndef HAVE_GNU_LD
+#define __tzname tzname
+#define __daylight daylight
+#define __timezone timezone
+#endif
+
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. */
+ unsigned char isstd; /* Transition times are standard time. */
};
struct leap
{
- time_t transition;
- long int change;
+ time_t transition; /* Time the transition takes effect. */
+ long int change; /* Seconds of correction to apply. */
};
static size_t num_transitions;
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)
+ if (num_transitions > 0)
{
- leaps = (struct leap *) malloc(num_leaps * sizeof(struct leap));
+ 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;
+ }
+ if (num_types > 0)
+ {
+ types = (struct ttinfo *) malloc (num_types * sizeof (struct ttinfo));
+ if (types == NULL)
+ goto lose;
+ }
+ if (chars > 0)
+ {
+ 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;
}
fread((PTR) type_idxs, 1, num_transitions, f) != num_transitions)
goto lose;
+ for (i = 0; i < num_transitions; ++i)
+ transitions[i] = uc2ul (&transitions[i]);
+
for (i = 0; i < num_types; ++i)
{
unsigned char x[4];
lose:;
(void) fclose(f);
}
+\f
+void
+DEFUN(__tzfile_default, (std, dst, stdoff, dstoff),
+ char *std AND char *dst AND
+ long int stdoff AND long int dstoff)
+{
+ size_t stdlen, dstlen, i;
+ __tzfile_read (TZDEFRULES);
+ if (!__use_tzfile)
+ return;
+
+ if (num_types < 2)
+ {
+ __use_tzfile = 0;
+ return;
+ }
+
+ free (zone_names);
+ stdlen = strlen (std) + 1;
+ dstlen = strlen (dst) + 1;
+ zone_names = malloc (stdlen + dstlen);
+ if (zone_names == NULL)
+ {
+ __use_tzfile = 0;
+ return;
+ }
+ memcpy (zone_names, std, stdlen);
+ memcpy (&zone_names[stdlen], dst, dstlen);
+
+ for (i = 0; i < num_types; ++i)
+ if (types[i].isdst)
+ {
+ types[i].idx = stdlen;
+ if (dst[0] != '\0')
+ types[i].offset = dstoff;
+ }
+ else
+ {
+ types[i].idx = 0;
+ if (dst[0] != '\0')
+ types[i].offset = stdoff;
+ }
+}
+\f
int
-DEFUN(__tzfile_compute, (timer, tm), time_t timer AND struct tm tm)
+DEFUN(__tzfile_compute, (timer, leap_correct, leap_hit),
+ time_t timer AND long int *leap_correct AND int *leap_hit)
{
struct ttinfo *info;
register size_t i;
- /* Find the first transition after TIMER, and then go back one. */
- i = 0;
- while (i < num_transitions && transitions[i] < timer)
- ++i;
- if (i == num_transitions)
- i = 0;
+ if (num_transitions == 0 || timer < transitions[0])
+ {
+ /* TIMER is before any transition (or there are no transitions).
+ Choose the first non-DST type
+ (or the first if they're all DST types). */
+ i = 0;
+ while (i < num_types && types[i].isdst)
+ ++i;
+ if (i == num_types)
+ i = 0;
+ }
else
- --i;
+ {
+ /* Find the first transition after TIMER, and
+ then pick the type of the transition before it. */
+ for (i = 1; i < num_transitions; ++i)
+ if (timer < transitions[i])
+ break;
+ i = type_idxs[i - 1];
+ }
- info = &types[type_idxs[i]];
+ info = &types[i];
__daylight = info->isdst;
__timezone = info->offset;
for (i = 0; i < num_types && i < sizeof (__tzname) / sizeof (__tzname[0]);
++i)
__tzname[types[i].isdst] = &zone_names[types[i].idx];
+ if (info->isdst < sizeof (__tzname) / sizeof (__tzname[0]))
+ __tzname[info->isdst] = &zone_names[info->idx];
+
+ *leap_correct = 0L;
+ *leap_hit = 0;
+ /* Find the last leap second correction transition time before TIMER. */
i = num_leaps;
do
if (i-- == 0)
return 1;
while (timer < leaps[i].transition);
- __timezone += leaps[i].change;
+
+ /* Apply its correction. */
+ *leap_correct = leaps[i].change;
+
+ if (timer == leaps[i].transition && /* Exactly at the transition time. */
+ ((i == 0 && leaps[i].change > 0) ||
+ leaps[i].change > leaps[i - 1].change))
+ {
+ *leap_hit = 1;
+ while (i > 0 &&
+ leaps[i].transition == leaps[i - 1].transition + 1 &&
+ leaps[i].change == leaps[i - 1].change + 1)
+ {
+ ++*leap_hit;
+ --i;
+ }
+ }
+
return 1;
}