summaryrefslogtreecommitdiff
path: root/src/vmstime.c
diff options
context:
space:
mode:
authorJim Blandy <jimb@redhat.com>1993-03-14 22:49:14 +0000
committerJim Blandy <jimb@redhat.com>1993-03-14 22:49:14 +0000
commit229f0363913547c7144471421ec681ccc6532d92 (patch)
tree0a307937ff87e97c1e0143da9849da13a7b34615 /src/vmstime.c
parent7f05aa0f80f0ea84da0617eddbc928b442c3f105 (diff)
downloademacs-229f0363913547c7144471421ec681ccc6532d92.tar.gz
Initial revision
Diffstat (limited to 'src/vmstime.c')
-rw-r--r--src/vmstime.c357
1 files changed, 357 insertions, 0 deletions
diff --git a/src/vmstime.c b/src/vmstime.c
new file mode 100644
index 00000000000..907ec350ca8
--- /dev/null
+++ b/src/vmstime.c
@@ -0,0 +1,357 @@
+#include "config.h"
+#include "vmstime.h"
+
+long timezone=0;
+int daylight=0;
+
+static char tzname_default[20]="";
+static char tzname_dst[20]="";
+
+char *tzname[2] = { tzname_default, tzname_dst };
+
+static long internal_daylight=0;
+static char daylight_set=0;
+
+static long read_time(const char *nptr, const char **endptr,
+ int sign_allowed_p)
+{
+ int t;
+
+ *endptr = nptr;
+
+ /* This routine trusts the user very much, and does no checks!
+ The only exception is this: */
+ if (!sign_allowed_p && (*nptr == '-' || *nptr == '+'))
+ return 0;
+
+ t = strtol(*endptr, endptr, 10) * 3600;
+ if (**endptr != ':' || **endptr == '+' || **endptr == '-')
+ return t;
+ (*endptr)++;
+
+ t = t + strtol(*endptr, endptr, 10) * 60;
+ if (**endptr != ':' || **endptr == '+' || **endptr == '-')
+ return t;
+ (*endptr)++;
+
+ return t + strtol(*endptr, endptr, 10);
+}
+
+static void read_dst_time(const char *nptr, const char **endptr,
+ int *m, int *n, int *d,
+ int *leap_p)
+{
+ time_t bintim = time(0);
+ struct tm *lc = localtime(&bintim);
+
+ *leap_p = 1;
+ *m = 0; /* When m and n are 0, a Julian */
+ *n = 0; /* date has been inserted in d */
+
+ switch(*nptr)
+ {
+ case 'M':
+ {
+ /* This routine counts on the user to have specified "Mm.n.d",
+ where 1 <= n <= 5, 1 <= m <= 12, 0 <= d <= 6 */
+
+ *m = strtol(++nptr, endptr, 10);
+ (*endptr)++; /* Skip the dot */
+ *n = strtol(*endptr, endptr, 10);
+ (*endptr)++; /* Skip the dot */
+ *d = strtol(*endptr, endptr, 10);
+
+ return;
+ }
+ case 'J':
+ *leap_p = 0; /* Never count with leap years */
+ default: /* trust the user to have inserted a number! */
+ *d = strtol(++nptr, endptr, 10);
+ return;
+ }
+}
+
+struct vms_vectim
+{
+ short year, month, day, hour, minute, second, centi_second;
+};
+static void find_dst_time(int m, int n, long d,
+ int hour, int minute, int second,
+ int leap_p,
+ long vms_internal_time[2])
+{
+ long status = SYS$GETTIM(vms_internal_time);
+ struct vms_vectim vms_vectime;
+ status = SYS$NUMTIM(&vms_vectime, vms_internal_time);
+
+ if (m == 0 && n == 0)
+ {
+ long tmp_vms_internal_time[2][2];
+ long day_of_year;
+ long tmp_operation = LIB$K_DAY_OF_YEAR;
+
+ status = LIB$CVT_FROM_INTERNAL_TIME(&tmp_operation, &day_of_year,
+ vms_internal_time);
+
+ vms_vectime.month = 2;
+ vms_vectime.day = 29;
+ status = LIB$CVT_VECTIM(&vms_vectime, tmp_vms_internal_time[0]);
+ if (status & 1) /* This is a leap year */
+ {
+ if (!leap_p && d > 59)
+ d ++; /* If we don't count with 29th Feb,
+ and this is a leap year, count up,
+ to make day 60 really become the
+ 1st March. */
+ }
+ /* 1st January, at midnight */
+ vms_vectime.month = 1;
+ vms_vectime.day = 1;
+ vms_vectime.hour = hour;
+ vms_vectime.minute = minute;
+ vms_vectime.second = second;
+ vms_vectime.centi_second = 0;
+ status = LIB$CVT_VECTIM(&vms_vectime, tmp_vms_internal_time[0]);
+ tmp_operation = LIB$K_DELTA_DAYS;
+ status = LIB$CVT_TO_INTERNAL_TIME(&tmp_operation, &d,
+ tmp_vms_internal_time[1]);
+ /* now, tmp_vms_interval_time[0] contains 1st Jan, 00:00:00,
+ and tmp_vms_interval_time[1] contains delta time +d days.
+ Let's just add them together */
+ status = LIB$ADD_TIMES(tmp_vms_internal_time[0],
+ tmp_vms_internal_time[1],
+ vms_internal_time);
+ }
+ else
+ {
+ long tmp_vms_internal_time[2];
+ long day_of_week;
+ long tmp_operation = LIB$K_DAY_OF_YEAR;
+
+ if (d == 0) /* 0 is Sunday, which isn't compatible with VMS,
+ where day_of_week is 1 -- 7, and 1 is Monday */
+ {
+ d = 7; /* So a simple conversion is required */
+ }
+ vms_vectime.month = m;
+ vms_vectime.day = 1;
+ vms_vectime.hour = hour;
+ vms_vectime.minute = minute;
+ vms_vectime.second = second;
+ vms_vectime.centi_second = 0;
+ status = LIB$CVT_VECTIM(&vms_vectime, tmp_vms_internal_time);
+ tmp_operation = LIB$K_DAY_OF_WEEK;
+ status = LIB$CVT_FROM_INTERNAL_TIME(&tmp_operation, &day_of_week,
+ tmp_vms_internal_time);
+ d -= day_of_week;
+ if (d < 0)
+ {
+ d += 7;
+ }
+ vms_vectime.day += (n-1)*7 + d;
+ status = LIB$CVT_VECTIM(&vms_vectime, vms_internal_time);
+ if (!(status & 1))
+ {
+ vms_vectime.day -= 7; /* n was probably 5 */
+ status = LIB$CVT_VECTIM(&vms_vectime, vms_internal_time);
+ }
+ }
+}
+
+static cmp_vms_internal_times(long vms_internal_time1[2],
+ long vms_internal_time2[2])
+{
+ if (vms_internal_time1[1] < vms_internal_time2[1])
+ return -1;
+ else
+ if (vms_internal_time1[1] > vms_internal_time2[1])
+ return 1;
+
+ if (vms_internal_time1[0] < vms_internal_time2[0])
+ return -1;
+ else
+ if (vms_internal_time1[0] > vms_internal_time2[0])
+ return 1;
+
+ return 0;
+}
+
+/* -------------------------- Global routines ------------------------------ */
+
+#ifdef tzset
+#undef tzset
+#endif
+void sys_tzset()
+{
+ char *TZ;
+ char *p, *q;
+
+ if (daylight_set)
+ return;
+
+ daylight = 0;
+
+ if ((TZ = getenv("TZ")) == 0)
+ return;
+
+ p = TZ;
+ q = tzname[0];
+
+ while(*p != '\0'
+ && (*p <'0' || *p > '9') && *p != '-' && *p != '+' && *p != ',')
+ *q++ = *p++;
+ *q = '\0';
+
+ /* This is special for VMS, so I don't care if it doesn't exist anywhere
+ else */
+
+ timezone = read_time(p, &p, 1);
+
+ q = tzname[1];
+
+ while(*p != '\0'
+ && (*p <'0' || *p > '9') && *p != '-' && *p != '+' && *p != ',')
+ *q++ = *p++;
+ *q = '\0';
+
+ if (*p != '-' && *p != '+' && !(*p >='0' && *p <= '9'))
+ internal_daylight = timezone - 3600;
+ else
+ internal_daylight = read_time(p, &p, 1);
+
+ if (*p == ',')
+ {
+ int start_m;
+ int start_n;
+ int start_d;
+ int start_leap_p;
+ int start_hour=2, start_minute=0, start_second=0;
+
+ p++;
+ read_dst_time(p, &p, &start_m, &start_n, &start_d, &start_leap_p);
+ if (*p == '/')
+ {
+ long tmp = read_time (++p, &p, 0);
+ start_hour = tmp / 3600;
+ start_minute = (tmp % 3600) / 60;
+ start_second = tmp % 60;
+ }
+ if (*p == ',')
+ {
+ int end_m;
+ int end_n;
+ int end_d;
+ int end_leap_p;
+ int end_hour=2, end_minute=0, end_second=0;
+
+ p++;
+ read_dst_time(p, &p, &end_m, &end_n, &end_d, &end_leap_p);
+ if (*p == '/')
+ {
+ long tmp = read_time (++p, &p, 0);
+ end_hour = tmp / 3600;
+ end_minute = (tmp % 3600) / 60;
+ end_second = tmp % 60;
+ }
+ {
+ long vms_internal_time[3][2];
+ find_dst_time(start_m, start_n, start_d,
+ start_hour, start_minute, start_second,
+ start_leap_p,
+ vms_internal_time[0]);
+ SYS$GETTIM(&vms_internal_time[1]);
+ find_dst_time(end_m, end_n, end_d,
+ end_hour, end_minute, end_second,
+ end_leap_p,
+ vms_internal_time[2]);
+ if (cmp_vms_internal_times(vms_internal_time[0],
+ vms_internal_time[1]) < 0
+ && cmp_vms_internal_times(vms_internal_time[1],
+ vms_internal_time[2]) < 0)
+ daylight = 1;
+ }
+ }
+ }
+}
+
+#ifdef localtime
+#undef localtime
+#endif
+struct tm *sys_localtime(time_t *clock)
+{
+ struct tm *tmp = localtime(clock);
+
+ sys_tzset();
+ tmp->tm_isdst = daylight;
+
+ return tmp;
+}
+
+#ifdef gmtime
+#undef gmtime
+#endif
+struct tm *sys_gmtime(time_t *clock)
+{
+ static struct tm gmt;
+ struct vms_vectim tmp_vectime;
+ long vms_internal_time[3][2];
+ long tmp_operation = LIB$K_DELTA_SECONDS;
+ long status;
+ long tmp_offset;
+ char tmp_o_sign;
+
+ sys_tzset();
+
+ if (daylight)
+ tmp_offset = internal_daylight;
+ else
+ tmp_offset = timezone;
+
+ if (tmp_offset < 0)
+ {
+ tmp_o_sign = -1;
+ tmp_offset = -tmp_offset;
+ }
+ else
+ tmp_o_sign = 1;
+
+ status = LIB$CVT_TO_INTERNAL_TIME(&tmp_operation, &tmp_offset,
+ vms_internal_time[1]);
+ status = SYS$GETTIM(vms_internal_time[0]);
+ if (tmp_o_sign < 0)
+ {
+ status = LIB$SUB_TIMES(vms_internal_time[0],
+ vms_internal_time[1],
+ vms_internal_time[2]);
+ }
+ else
+ {
+ status = LIB$ADD_TIMES(vms_internal_time[0],
+ vms_internal_time[1],
+ vms_internal_time[2]);
+ }
+
+ status = SYS$NUMTIM(&tmp_vectime, vms_internal_time[2]);
+ gmt.tm_sec = tmp_vectime.second;
+ gmt.tm_min = tmp_vectime.minute;
+ gmt.tm_hour = tmp_vectime.hour;
+ gmt.tm_mday = tmp_vectime.day;
+ gmt.tm_mon = tmp_vectime.month - 1;
+ gmt.tm_year = tmp_vectime.year % 100;
+
+ tmp_operation = LIB$K_DAY_OF_WEEK;
+ status = LIB$CVT_FROM_INTERNAL_TIME(&tmp_operation,
+ &gmt.tm_wday,
+ vms_internal_time[2]);
+ if (gmt.tm_wday == 7) gmt.tm_wday = 0;
+
+ tmp_operation = LIB$K_DAY_OF_YEAR;
+ status = LIB$CVT_FROM_INTERNAL_TIME(&tmp_operation,
+ &gmt.tm_yday,
+ vms_internal_time[2]);
+ gmt.tm_yday--;
+ gmt.tm_isdst = daylight;
+
+ return &gmt;
+}
+