-/* Copyright (C) 1991, 1992 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;
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;
}
else
{
- /* Find the first transition after TIMER, and then go back one. */
- i = 1;
- while (i < num_transitions && transitions[i] < timer)
- ++i;
- --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]);
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;
}