made a lot of changes
authoreck <none@none>
Mon, 18 Dec 1989 15:33:48 +0000 (15:33 +0000)
committereck <none@none>
Mon, 18 Dec 1989 15:33:48 +0000 (15:33 +0000)
14 files changed:
lang/cem/libcc.ansi/time/.distr [new file with mode: 0644]
lang/cem/libcc.ansi/time/LIST
lang/cem/libcc.ansi/time/Makefile [new file with mode: 0644]
lang/cem/libcc.ansi/time/asctime.c
lang/cem/libcc.ansi/time/clock.c
lang/cem/libcc.ansi/time/difftime.c
lang/cem/libcc.ansi/time/gmtime.c
lang/cem/libcc.ansi/time/loc_incl.h
lang/cem/libcc.ansi/time/localtime.c
lang/cem/libcc.ansi/time/misc.c
lang/cem/libcc.ansi/time/mktime.c
lang/cem/libcc.ansi/time/strftime.c
lang/cem/libcc.ansi/time/time.c
lang/cem/libcc.ansi/time/tzset.c

diff --git a/lang/cem/libcc.ansi/time/.distr b/lang/cem/libcc.ansi/time/.distr
new file mode 100644 (file)
index 0000000..bde041f
--- /dev/null
@@ -0,0 +1,14 @@
+LIST
+Makefile
+asctime.c
+clock.c
+ctime.c
+difftime.c
+gmtime.c
+loc_incl.h
+localtime.c
+misc.c
+mktime.c
+strftime.c
+time.c
+tzset.c
index a1c39e5..6dfc5bb 100644 (file)
@@ -1,4 +1,3 @@
-tlib
 loc_incl.h
 ctime.c
 asctime.c
diff --git a/lang/cem/libcc.ansi/time/Makefile b/lang/cem/libcc.ansi/time/Makefile
new file mode 100644 (file)
index 0000000..8d9360b
--- /dev/null
@@ -0,0 +1,22 @@
+CFLAGS=-L -LIB
+
+.SUFFIXES: .o .e .c
+
+.e.o:
+       $(CC) $(CFLAGS) -c -o $@ $*.e
+
+clean:
+       rm -rf ctime.o asctime.o localtime.o clock.o difftime.o gmtime.o \
+               mktime.o strftime.o time.o tzset.o misc.o OLIST
+
+ctime.o:
+asctime.o:
+localtime.o:
+clock.o:
+difftime.o:
+gmtime.o:
+mktime.o:
+strftime.o:
+time.o:
+tzset.o:
+misc.o:
index d0efa25..8011624 100644 (file)
@@ -3,7 +3,6 @@
  */
 /* $Header$ */
 
-#include       <stdio.h>
 #include       <string.h>
 #include       <time.h>
 #include       "loc_incl.h"
@@ -36,7 +35,8 @@ four_digits(register char *pb, int i)
 char *asctime(const struct tm *timeptr)
 {
        static char buf[26];
-       register char *pb = buf, *ps;
+       register char *pb = buf;
+       register const char *ps;
        register int n;
 
        strcpy(pb, DATE_STR);
index 06faa7e..2b9b08c 100644 (file)
@@ -4,16 +4,82 @@
 /* $Header$ */
 
 #include       <time.h>
-#include       <sys/time.h>
-#include       <sys/resource.h>
+
+#if    defined(__BSD4_2)
+
+struct timeval {
+       long    tv_sec;                 /* seconds */
+       long    tv_usec;                /* and microseconds */
+};
+
+#define        RUSAGE_SELF     0
+#define        RUSAGE_CHILDREN -1
+
+struct rusage {
+       struct timeval ru_utime;        /* user time used */
+       struct timeval ru_stime;        /* system time used */
+       long    ru_maxrss;
+       long    ru_ixrss;               /* integral shared memory size */
+       long    ru_idrss;               /* integral unshared data size */
+       long    ru_isrss;               /* integral unshared stack size */
+       long    ru_minflt;              /* page reclaims */
+       long    ru_majflt;              /* page faults */
+       long    ru_nswap;               /* swaps */
+       long    ru_inblock;             /* block input operations */
+       long    ru_oublock;             /* block output operations */
+       long    ru_msgsnd;              /* messages sent */
+       long    ru_msgrcv;              /* messages received */
+       long    ru_nsignals;            /* signals received */
+       long    ru_nvcsw;               /* voluntary context switches */
+       long    ru_nivcsw;              /* involuntary context switches */
+};
+
+void getrusage(int who, struct rusage *rusage);
+
+#elif  defined(_POSIX_SOURCE) || defined(__USG)
+
+struct tms {
+       time_t  tms_utime;              /* user time */
+       time_t  tms_stime;              /* system time */
+       time_t  tms_cutime;             /* user time, children */
+       time_t  tms_cstime;             /* system time, children */
+};
+
+long times(struct tms *buffer);
+
+#else                                  /* Version 7 UNIX */
+
+struct tbuffer {
+       long proc_user_time;
+       long proc_system_time;
+       long child_user_time;
+       long child_system_time;
+};
+
+long times(struct tbuffer *buffer);
+
+#endif
 
 clock_t
 clock(void)
 {
+#if    defined(__BSD4_2)
        struct rusage rusage;
 
        getrusage(RUSAGE_SELF, &rusage);
 
-       return (((unsigned long)rusage.ru_utime.tv_sec * CLK_TCK)
-                   + rusage.ru_utime.tv_usec);
+       return (((unsigned long)rusage.ru_utime.tv_sec * CLOCKS_PER_SEC)
+               + rusage.ru_utime.tv_usec);
+#elif  defined(_POSIX_SOURCE) || defined(__USG)
+       struct tms tms;
+
+       times(&tms);
+       /* Assume that time_t can be converted to clock_t for Sys5 */
+       return tms.tms_utime;
+#else
+       struct tbuffer tbuffer;
+
+       times(&tbuffer);
+       return tbuffer.proc_user_time;
+#endif
 }
index c0de014..6b1ba72 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * difftime - compute the difference bnetween two calendar times
+ * difftime - compute the difference between two calendar times
  */
 /* $Header$ */
 
index 07285d0..0d078cc 100644 (file)
@@ -14,7 +14,7 @@ gmtime(register const time_t *timer)
        register struct tm *timep = &br_time;
        time_t time = *timer;
        register unsigned long dayclock, dayno;
-       int year = 1970;
+       int year = EPOCH_YR;
 
        dayclock = time % SECS_DAY;
        dayno = time / SECS_DAY;
@@ -27,7 +27,7 @@ gmtime(register const time_t *timer)
                dayno -= YEARSIZE(year);
                year++;
        }
-       timep->tm_year = year - YEAR1;
+       timep->tm_year = year - YEAR0;
        timep->tm_yday = dayno;
        timep->tm_mon = 0;
        while (dayno >= _ytab[LEAPYEAR(year)][timep->tm_mon]) {
index 3e72c54..5ccbb4c 100644 (file)
@@ -3,18 +3,24 @@
  */
 /* $Header$ */
 
-#define        YEAR1           1900                    /* the first year */
+#define        YEAR0           1900                    /* the first year */
+#define        EPOCH_YR        1970            /* EPOCH = Jan 1 1970 00:00:00 */
 #define        SECS_DAY        (24L * 60L * 60L)
 #define        LEAPYEAR(year)  (!((year) % 4) && (((year) % 100) || !((year) % 400)))
 #define        YEARSIZE(year)  (LEAPYEAR(year) ? 366 : 365)
-#define        FIRSTSUNDAY(year)       (((year)->tm_yday - (year)->tm_wday + 420) % 7)
+#define        FIRSTSUNDAY(timp)       (((timp)->tm_yday - (timp)->tm_wday + 420) % 7)
+#define        FIRSTDAYOF(timp)        (((timp)->tm_wday - (timp)->tm_yday + 420) % 7)
 #define        TIME_MAX        ULONG_MAX
 #define        ABB_LEN         3
 
 extern const int _ytab[2][12];
 extern const char *_days[];
 extern const char *_months[];
-extern char *__tzname[];
 
-long int _tzone(void);
+void _tzset(void);
 unsigned _dstget(struct tm *timep);
+
+extern long _timezone;
+extern long _dst_off;
+extern int _daylight;
+extern char *_tzname[2];
index df90fd9..871bfdf 100644 (file)
@@ -16,16 +16,18 @@ struct tm *
 localtime(const time_t *timer)
 {
        struct tm *timep;
-       long tz = _tzone();
        unsigned dst;
 
+       _tzset();
        timep = gmtime(timer);                  /* tm->tm_isdst == 0 */
-       timep->tm_min -= tz / 60;
+       timep->tm_min -= _timezone / 60;
+       timep->tm_sec -= _timezone % 60;
        mktime(timep);
 
        dst = _dstget(timep);
        if (dst) {
                timep->tm_min += dst / 60;
+               timep->tm_sec += dst % 60;
                mktime(timep);
        }
        return timep;
index 557a12b..ec0b945 100644 (file)
  */
 /* $Header$ */
 
+#include       <ctype.h>
 #include       <time.h>
 #include       <stdlib.h>
 #include       <string.h>
 
-#ifdef __BSD4_2
-#include       <sys/time.h>
-#elif  !defined(__USG)
-struct timeb
-{
-       timez_t time;
-       unsigned short millitm;
-       short timezone;
-       short dstflag;
+#if    defined(__BSD4_2)
+
+struct timeval {
+       long    tv_sec;         /* seconds */
+       long    tv_usec;        /* and microseconds */
+};
+
+struct timezone {
+       int     tz_minuteswest; /* minutes west of Greenwich */
+       int     tz_dsttime;     /* type of dst correction */
+};
+
+int gettimeofday(struct timeval *tp, struct timezone *tzp);
+
+#elif !defined(_POSIX_SOURCE) && !defined(__USG)
+#if    !defined(_MINIX)        /* MINIX has no ftime() */
+struct timeb {
+       long    time;
+       undigned short millitm;
+       short   timezone;
+       short   dstflag;
 };
+void ftime(struct timeb *bp);
+#endif
 #endif
 
 #include       "loc_incl.h"
 
-#ifdef __USG
-long   timezone = -1 * 60;
+/* The following define of TZ_LEN must match the number of characters
+ * of the elements of tzname.
+ */
+#define        TZ_LEN          10
+#define        RULE_LEN        120
+
+#if    defined(__USG) || defined(_POSIX_SOURCE)
+char   *tzname[2] = {"MET\0\0\0\0\0\0\0", "MDT\0\0\0\0\0\0\0"};
+
+#if    defined(__USG)
+long   timezone = -1 * 60 * 60;
 int    daylight = 1;
-char   *tzname[] = {"MET", "MDT",};
 #endif
+#endif
+
+long   _timezone = -1 * 60 * 60;
+long   _dst_off = 60 * 60;
+int    _daylight = -1;
+char   *_tzname[2] = {"MET\0\0\0\0\0\0\0", "MDT\0\0\0\0\0\0\0"};
 
-long   __timezone = -1 * 60;
-static int __daylight = 1;
-char   *__tzname[] = {"MET", "MDT",};
+static struct dsttype {
+       char ds_type;           /* Unknown, Julian, Zero-based or M */
+       int ds_date[3];         /* months, weeks, days */
+       long ds_sec;            /* usually 02:00:00 */
+}      dststart = { 'U', { 0, 0, 0 }, 2 * 60 * 60 }
+       , dstend = { 'U', { 0, 0, 0 }, 2 * 60 * 60 };
 
 const char *_days[] = {
-                   "Sunday", "Monday", "Tuesday", "Wednesday",
-                   "Thursday", "Friday", "Saturday"
-           };
+                       "Sunday", "Monday", "Tuesday", "Wednesday",
+                       "Thursday", "Friday", "Saturday"
+               };
 
 const char *_months[] = {
-                   "January", "February", "March",
-                   "April", "May", "June",
-                   "July", "August", "September",
-                   "October", "November", "December"
-           };
+                       "January", "February", "March",
+                       "April", "May", "June",
+                       "July", "August", "September",
+                       "October", "November", "December"
+               };
 
 const int _ytab[2][12] = {
                { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
                { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
        };
 
-int
-_leap(int year)
+static const char *
+parseZoneName(register char *buf, register const char *p)
+{
+       register int n = 0;
+
+       if (*p == ':') return NULL;
+       while (*p && !isdigit(*p) && *p != ',' && *p != '-' && *p != '+') {
+               if (n < TZ_LEN)
+                       *buf++ = *p;
+               p++;
+               n++;
+       }
+       if (n < 3) return NULL;                         /* error */
+       *buf = '\0';
+       return p;
+}
+
+static const char *
+parseTime(register long *tm, const char *p, register struct dsttype *dst)
 {
-       return (!(year % 4) && ((year % 100) || !(year % 400)));
+       register int n = 0;
+       register const char *q = p;
+       char ds_type = (dst ? dst->ds_type : '\0');
+
+       if (dst) dst->ds_type = 'U';
+
+       *tm = 0;
+       while(*p >= '0' && *p <= '9') {
+               n = 10 * n + (*p++ - '0');
+       }
+       if (q == p) return NULL;        /* "The hour shall be required" */
+       if (n < 0 || n >= 24)   return NULL;
+       *tm = n * 60 * 60;
+       if (*p == ':') {
+               p++;
+               n = 0;
+               while(*p >= '0' && *p <= '9') {
+                       n = 10 * n + (*p++ - '0');
+               }
+               if (q == p) return NULL;        /* format error */
+               if (n < 0 || n >= 60)   return NULL;
+               *tm += n * 60;
+               if (*p == ':') {
+                       p++;
+                       n = 0;
+                       while(*p >= '0' && *p <= '9') {
+                               n = 10 * n + (*p++ - '0');
+                       }
+                       if (q == p) return NULL;        /* format error */
+                       if (n < 0 || n >= 60)   return NULL;
+                       *tm += n;
+               }
+       }
+       if (dst) {
+               dst->ds_type = ds_type;
+               dst->ds_sec = *tm;
+       }
+       return p;
 }
 
-long
-_tzone(void)
+static const char *
+parseDate(register char *buf, register const char *p, struct dsttype *dstinfo)
 {
-       register char *p = getenv("TZ");
+       register const char *q;
        register int n = 0;
-       int sign = 1;
+       int cnt = 0;
+       const int bnds[3][2] =  {       { 1, 12 },
+                                       { 1, 5 },
+                                       { 0, 6}
+                                };
+       char ds_type;
+
+       if (*p != 'M') {
+               if (*p == 'J') {
+                       *buf++ = *p++;
+                       ds_type = 'J';
+               }
+               else    ds_type = 'Z';
+               q = p;
+               while(*p >= '0' && *p <= '9') {
+                       n = 10 * n + (*p - '0');
+                       *buf++ = *p++;
+               }
+               if (q == p) return NULL;        /* format error */
+               if (n < (ds_type == 'J') || n > 365) return NULL;
+               dstinfo->ds_type = ds_type;
+               dstinfo->ds_date[0] = n;
+               return p;
+       }
+       ds_type = 'M';
+       do {
+               *buf++ = *p++;
+               q = p;
+               n = 0;
+               while(*p >= '0' && *p <= '9') {
+                       n = 10 * n + (*p - '0');
+                       *buf++ = *p++;
+               }
+               if (q == p) return NULL;        /* format error */
+               if (n < bnds[cnt][0] || n > bnds[cnt][1]) return NULL;
+               dstinfo->ds_date[cnt] = n;
+               cnt++;
+       } while (cnt < 3 && *p == '.');
+       if (cnt != 3) return NULL;
+       *buf = '\0';
+       dstinfo->ds_type = ds_type;
+       return p;
+}
+
+static const char *
+parseRule(register char *buf, register const char *p)
+{
+       long time;
+       register const char *q;
+
+       if (!(p = parseDate(buf, p, &dststart))) return NULL;
+       buf += strlen(buf);
+       if (*p == '/') {
+               q = ++p;
+               if (!(p = parseTime(&time, p, &dststart))) return NULL;
+               while( p != q) *buf++ = *q++;
+       }
+       if (*p != ',') return NULL;
+       p++;
+       if (!(p = parseDate(buf, p, &dstend))) return NULL;
+       buf += strlen(buf);
+       if (*p == '/') {
+               q = ++p;
+               if (!(p = parseTime(&time, p, &dstend))) return NULL;
+               while(*buf++ = *q++);
+       }
+       if (*p) return NULL;
+       return p;
+}
+
+/* The following routine parses timezone information in POSIX-format. For
+ * the requirements, see IEEE Std 1003.1-1988 section 8.1.1.
+ * The function returns as soon as it spots an error.
+ */
+static void
+parseTZ(const char *p)
+{
+       register int n;
+       long tz, dst = 60 * 60, sign = 1;
+       static char lastTZ[2 * RULE_LEN];
+       static char buffer[RULE_LEN];
+
+       if (!p) return;
+
+       if (!strcmp(lastTZ, p)) return;         /* nothing changed */
+
+       *_tzname[0] = '\0';
+       *_tzname[1] = '\0';
+       dststart.ds_type = 'U';
+       dststart.ds_sec = 2 * 60 * 60;
+       dstend.ds_type = 'U';
+       dstend.ds_sec = 2 * 60 * 60;
+
+       if (strlen(p) > 2 * RULE_LEN) return;
+       strcpy(lastTZ, p);
+
+       if (!(p = parseZoneName(buffer, p))) return;
+
+       if (*p == '-') {
+               sign = -1;
+               p++;
+       } else if (*p == '+') p++;
+
+       if (!(p = parseTime(&tz, p, NULL))) return;
+       tz *= sign;
+       _timezone = tz;
+       strncpy(_tzname[0], buffer, TZ_LEN);
+
+       if (!(_daylight = (*p != '\0'))) return;
+
+       buffer[0] = '\0';
+       if (!(p = parseZoneName(buffer, p))) return;
+       strncpy(_tzname[1], buffer, TZ_LEN);
+
+       buffer[0] = '\0';
+       if (*p && (*p != ','))
+               if (!(p = parseTime(&dst, p, NULL))) return;
+       _dst_off = dst;                 /* dst was initialized to 1 hour */
+       if (*p) {
+               if (*p != ',') return;
+               p++;
+               if (strlen(p) > RULE_LEN) return;
+               if (!(p = parseRule(buffer, p))) return;
+       }
+}
+
+void
+_tzset(void)
+{
+#if    defined(__BSD4_2)
 
-#ifdef __BSD4_2
        struct timeval tv;
        struct timezone tz;
 
        gettimeofday(&tv, &tz);
-       __daylight = tz.tz_dsttime;
-       __timezone = tz.tz_minuteswest * 60;
+       _daylight = tz.tz_dsttime;
+       _timezone = tz.tz_minuteswest * 60;
 
-#elif !defined(__USG)
+#elif !defined(_POSIX_SOURCE) && !defined(__USG)
+
+#if    !defined(_MINIX)                /* MINIX has no ftime() */
        struct timeb time;
 
        ftime(&time);
-       __timezone = time.timezone * 60L;
-       __daylight = time.dstflag;
+       _timezone = time.timezone * 60L;
+       _daylight = time.dstflag;
 #endif
-       if (p && *p) {
-               strncpy(__tzname[0], p, 3);
-               p += 3;
-               if (*p == '-') {
-                       sign = -1;
-                       p++;
-               }
 
-               while (*p >= '0' && *p <= '9')
-                       n = 10 * n + (*p++ - '0');
-               n *= sign;
-               __timezone = ((long)(n * 60)) * 60;
-               __daylight = (*p != '\0');
-               strncpy(__tzname[1], p, 3);
-       }
-#ifdef __USG
-       timezone = __timezone;
-       daylight = __daylight;
-       tzname[0] = __tzname[0];
-       tzname[1] = __tzname[1];
+#endif /* !_POSIX_SOURCE && !__USG */
+
+       parseTZ(getenv("TZ"));          /* should go inside #if */
+
+#if    defined(__USG) || defined(_POSIX_SOURCE)
+       tzname[0] = _tzname[0];
+       tzname[1] = _tzname[1];
+#if    defined(__USG)
+       timezone = _timezone;
+       daylight = _daylight;
 #endif
-       return __timezone;
+#endif /* __USG || _POSIX_SOURCE */
 }
 
 static int
@@ -105,36 +312,79 @@ last_sunday(register int day, register struct tm *timep)
 {
        int first = FIRSTSUNDAY(timep);
 
-       if (day >= 58 && LEAPYEAR(1900 + timep->tm_year)) day++;
+       if (day >= 58 && LEAPYEAR(YEAR0 + timep->tm_year)) day++;
        if (day < first) return first;
        return day - (day - first) % 7;
 }
 
+static int
+date_of(register struct dsttype *dst, struct tm *timep)
+{
+       int leap = LEAPYEAR(YEAR0 + timep->tm_year);
+       int firstday, tmpday;
+       register int day, month;
+
+       if (dst->ds_type != 'M') {
+               return dst->ds_date[0] -
+                           (dst->ds_type == 'J'
+                               && leap
+                               && dst->ds_date[0] < 58);
+       }
+       day = 0;
+       month = 1;
+       while (month < dst->ds_date[0]) {
+               day += _ytab[leap][month - 1];
+               month++;
+       }
+       firstday = (day + FIRSTDAYOF(timep)) % 7;
+       tmpday = day;
+       day += (dst->ds_date[2] - firstday + 7) % 7
+               + 7 * (dst->ds_date[1] - 1);
+       if (day >= tmpday + _ytab[leap][month]) day -= 7;
+       return day;
+}
+
 unsigned
-_dstget(struct tm *timep)
+_dstget(register struct tm *timep)
 {
        int begindst, enddst;
+       register struct dsttype *dsts = &dststart, *dste = &dstend;
+
+       if (_daylight == -1)
+               _tzset();
+
+       timep->tm_isdst = _daylight;
+       if (!_daylight) return 0;
+
+       if (dsts->ds_type != 'U')
+               begindst = date_of(dsts, timep);
+       else begindst = last_sunday(89, timep); /* last Sun before Apr */
+       if (dste->ds_type != 'U')
+               enddst = date_of(dste, timep);
+       else enddst = last_sunday(272, timep);  /* last Sun in Sep */
+
+       /* assume begindst != enddst (otherwise it would be no use) */
+       if (begindst < enddst) {                /* northern hemisphere */
+               if (timep->tm_yday > begindst && timep->tm_yday < enddst)
+                       return _dst_off;
+       } else {                                /* southern hemisphere */
+               if (timep->tm_yday > begindst || timep->tm_yday < enddst)
+                       return _dst_off;
+       }
+
+       if (timep->tm_yday == begindst || timep->tm_yday == enddst) {
+               long dsttranssec;       /* transition when day is this old */
+               long cursec;
+
+               if (timep->tm_yday == begindst)
+                       dsttranssec = dsts->ds_sec;
+               else    dsttranssec = dste->ds_sec;
+               cursec = ((timep->tm_hour * 60) + timep->tm_min) * 60
+                           + timep->tm_sec;
 
-       if(__daylight == -1)
-               _tzone();
-
-       timep->tm_isdst = __daylight;
-       if (!__daylight) return 0;
-       begindst = last_sunday(89, timep);      /* last Sun before Apr */
-       enddst = last_sunday(272, timep);       /* last Sun in Sep */
-
-       /* The rules for daylight saving time differ for different coutries.
-        * Implemented here are heuristics that got it right in Holland for
-        * the last couple of years. There is, of course, no universal
-        * algorithm. Only tables would work perfect.
-        */
-       if ( (timep->tm_yday>begindst
-               || (timep->tm_yday == begindst && timep->tm_hour >= 2))
-           && (timep->tm_yday<enddst
-               || (timep->tm_yday == enddst && timep->tm_hour < 3))) {
-               /* it all happens between 2 and 3 */
-
-               return 60*60;
+               if ((timep->tm_yday == begindst && cursec >= dsttranssec)
+                   || (timep->tm_yday == enddst && cursec < dsttranssec))
+                       return _dst_off;
        }
        timep->tm_isdst = 0;
 
index ff83e0c..597f104 100644 (file)
@@ -7,16 +7,19 @@
 #include       <limits.h>
 #include       "loc_incl.h"
 
+/* The code assumes that time_t is an unsigned long. When it is not, some
+ * things may have to change.
+ */
 time_t
 mktime(register struct tm *timep)
 {
-       int day, year, month, yday;
-       long tmp_sec, tz = _tzone();
-       register time_t seconds, localseconds;
-       int overflow = 0;
+       register long day, year;
+       register int tm_year;
+       int yday, month;
+       register time_t seconds;
+       int overflow;
        unsigned dst;
 
-
        timep->tm_min += timep->tm_sec / 60;
        timep->tm_sec %= 60;
        if (timep->tm_sec < 0) {
@@ -43,87 +46,81 @@ mktime(register struct tm *timep)
        }
        day += (timep->tm_mday - 1);
        while (day < 0) {
-               day += YEARSIZE(YEAR1 + timep->tm_year - 1);
+               day += YEARSIZE(YEAR0 + timep->tm_year - 1);
                timep->tm_year--;
        }
-       while (day >= YEARSIZE(YEAR1 + timep->tm_year)) {
-               day -= YEARSIZE(YEAR1 + timep->tm_year);
+       while (day >= YEARSIZE(YEAR0 + timep->tm_year)) {
+               day -= YEARSIZE(YEAR0 + timep->tm_year);
                timep->tm_year++;
        }
-       while (day >= _ytab[LEAPYEAR(YEAR1 + timep->tm_year)][timep->tm_mon]) {
-               day -= _ytab[LEAPYEAR(YEAR1 + timep->tm_year)][timep->tm_mon];
+       while (day >= _ytab[LEAPYEAR(YEAR0 + timep->tm_year)][timep->tm_mon]) {
+               day -= _ytab[LEAPYEAR(YEAR0 + timep->tm_year)][timep->tm_mon];
                if (++(timep->tm_mon) == 12) {
                        timep->tm_mon = 0;
                        timep->tm_year++;
                }
        }
        timep->tm_mday = day + 1;
-       year = 70;
-       if (timep->tm_year < year) return -1;
+       _tzset();                       /* set timezone and dst info  */
+       year = EPOCH_YR;
+       if (timep->tm_year < year - YEAR0) return -1;
        seconds = 0;
-       while (!overflow && year < timep->tm_year) {
-               tmp_sec = SECS_DAY * YEARSIZE(YEAR1 + year);
-               if (TIME_MAX - tmp_sec <= seconds) overflow++;
-               else {
-                       seconds += tmp_sec;
-                       year++;
-               }
-       }
+       day = 0;                        /* means days since day 0 now */
+       overflow = 0;
+
+       /* Assume that when day becomes negative, there will certainly
+        * be overflow on seconds.
+        * The check for overflow needs not to be done for leapyears
+        * divisible by 400.
+        * The code only works when year (1970) is not a leapyear.
+        */
+#if    EPOCH_YR != 1970
+#error EPOCH_YR != 1970
+#endif
+       tm_year = timep->tm_year + YEAR0;
+
+       if (LONG_MAX / 365 < tm_year - year) overflow++;
+       day = (tm_year - year) * 365;
+       if (LONG_MAX - day < (tm_year - year) / 4 + 1) overflow++;
+       day += (tm_year - year) / 4
+               + ((tm_year % 4) && tm_year % 4 < year % 4);
+       day -= (tm_year - year) / 100
+               + ((tm_year % 100) && tm_year % 100 < year % 100);
+       day += (tm_year - year) / 400
+               + ((tm_year % 400) && tm_year % 400 < year % 400);
+
        yday = month = 0;
-       while (!overflow && month < timep->tm_mon) {
-               yday += _ytab[LEAPYEAR(YEAR1 + year)][month];
+       while (month < timep->tm_mon) {
+               yday += _ytab[LEAPYEAR(tm_year)][month];
                month++;
        }
        yday += (timep->tm_mday - 1);
-       if (!overflow) {
-               tmp_sec = yday * SECS_DAY;
-               if (TIME_MAX - tmp_sec <= seconds) overflow++;
-               else seconds += tmp_sec;
-       }
-
-       timep->tm_yday = yday;          /* ??? assignments should be later */
-                                       /* day 0 was thursday (4) */
-       timep->tm_wday = (seconds / SECS_DAY + 4) % 7;
+       if (day + yday < 0) overflow++;
+       day += yday;
 
-       if (timep->tm_isdst < 0)
-               dst = _dstget(timep);
-       else if (timep->tm_isdst)
-               dst = 60 * 60;
-       else dst = 0;
+       timep->tm_yday = yday;
+       timep->tm_wday = (day + 4) % 7;         /* day 0 was thursday (4) */
 
-       if (!overflow) {
-               tmp_sec = timep->tm_hour * 60 * 60;
-               if (TIME_MAX - tmp_sec <= seconds) overflow++;
-               else seconds += tmp_sec;
-       }
+       seconds = ((timep->tm_hour * 60) + timep->tm_min) * 60 + timep->tm_sec;
 
-       if (!overflow) {
-               tmp_sec = timep->tm_min * 60;
-               if (TIME_MAX - tmp_sec <= seconds) overflow++;
-               else seconds += tmp_sec;
-       }
+       if ((TIME_MAX - seconds) / SECS_DAY < day) overflow++;
+       seconds += day * SECS_DAY;
 
-       if (!overflow) {
-               tmp_sec = timep->tm_sec;
-               if (TIME_MAX - tmp_sec <= seconds) overflow++;
-               else seconds += tmp_sec;
-       }
+       /* Now adjust according to timezone and daylight saving time */
 
-       localseconds = seconds;
+       if (((_timezone > 0) && (TIME_MAX - _timezone < seconds))
+           || ((_timezone < 0) && (seconds < -_timezone)))
+               overflow++;
+       seconds += _timezone;
 
-       if (!overflow) {
-               tmp_sec = tz;
-               if (((tmp_sec > 0) && (TIME_MAX - tmp_sec <= seconds))
-                   || ((tmp_sec < 0) && (seconds < -tmp_sec)))
-                       overflow++;
-               else seconds += tmp_sec;
-       }
+       if (timep->tm_isdst < 0)
+               dst = _dstget(timep);
+       else if (timep->tm_isdst)
+               dst = _dst_off;
+       else dst = 0;
 
-       if (!overflow) {
-               tmp_sec = dst;
-               if (tmp_sec > seconds) overflow++;
-               else seconds -= tmp_sec;
-       }
+       if (dst > seconds) overflow++;  /* dst is always non-negative */
+       seconds -= dst;
 
        if (overflow) return (time_t)-1;
 
index 9827c6a..92f67b7 100644 (file)
@@ -6,7 +6,7 @@
 #include       <time.h>
 #include       "loc_incl.h"
 
-/* The width can be negative in both s_prnt() as in u_prnt(). This
+/* The width can be -1 in both s_prnt() as in u_prnt(). This
  * indicates that as many characters as needed should be printed.
  */
 static char *
@@ -43,14 +43,15 @@ strftime(char *s, size_t maxsize,
 
        if (!format) return 0;
 
+       _tzset();       /* for %Z conversion */
        firsts = s;
        while (maxsize && *format) {
-               if (maxsize && *format && *format != '%') {
+               while (maxsize && *format && *format != '%') {
                        *s++ = *format++;
                        maxsize--;
-                       continue;
                }
-               if (*format++ != '%') break;    /* maxsize == 0 || !*format */
+               if (!maxsize || !*format) break;
+               format++;
 
                olds = s;
                switch (*format++) {
@@ -75,7 +76,8 @@ strftime(char *s, size_t maxsize,
                case 'c':
                        n = strftime(s, maxsize,
                                        "%a %b %d %H:%M:%S %Y", timeptr);
-                       maxsize -= n;
+                       if (n) maxsize -= n;
+                       else maxsize = 0;
                        s += n;
                        break;
                case 'd':
@@ -128,12 +130,14 @@ strftime(char *s, size_t maxsize,
                        break;
                case 'x':
                        n = strftime(s, maxsize, "%a %b %d %Y", timeptr);
-                       maxsize -= n;
+                       if (n) maxsize -= n;
+                       else maxsize = 0;
                        s += n;
                        break;
                case 'X':
                        n = strftime(s, maxsize, "%H:%M:%S", timeptr);
-                       maxsize -= n;
+                       if (n) maxsize -= n;
+                       else maxsize = 0;
                        s += n;
                        break;
                case 'y':
@@ -141,12 +145,12 @@ strftime(char *s, size_t maxsize,
                        maxsize -= s - olds;
                        break;
                case 'Y':
-                       s = u_prnt(s, maxsize, timeptr->tm_year + 1900, -1);
+                       s = u_prnt(s, maxsize, timeptr->tm_year + YEAR0, -1);
                        maxsize -= s - olds;
                        break;
                case 'Z':
                        s = s_prnt(s, maxsize,
-                                       __tzname[(timeptr->tm_isdst > 0)], -1);
+                                       _tzname[(timeptr->tm_isdst > 0)], -1);
                        maxsize -= s - olds;
                        break;
                case '%':
index 4b85278..ba816c4 100644 (file)
@@ -3,17 +3,34 @@
  */
 /* $Header$ */
 
+#if    defined(__BSD4_2)
 #include       <time.h>
-#include       <sys/time.h>
+/*
+ * Structure returned by gettimeofday(2) system call,
+ * and used in other calls.
+ */
+struct timeval {
+       long    tv_sec;         /* seconds */
+       long    tv_usec;        /* and microseconds */
+};
+
+struct timezone {
+       int     tz_minuteswest; /* minutes west of Greenwich */
+       int     tz_dsttime;     /* type of dst correction */
+};
+
+int gettimeofday(struct timeval *tp, struct timezone *tzp);
 
 time_t
 time(time_t *timer)
 {
        struct timeval tv;
        struct timezone tz;
-
        gettimeofday(&tv, &tz);
 
        if (timer) *timer = tv.tv_sec;
        return tv.tv_sec;
 }
+#else
+/* Assume time() is a system call */   /* ??? */
+#endif
index e1ae1f3..53d4dcb 100644 (file)
@@ -1,9 +1,9 @@
 /*
- * tzset - system V compatibility
+ * tzset - set timezone information
  */
 /* $Header$ */
 
-#ifdef __USG
+/* This function is present for System V && POSIX */
 
 #include       <time.h>
 #include       "loc_incl.h"
@@ -11,6 +11,5 @@
 void
 tzset(void)
 {
-       _tzone();       /* does the job */
+       _tzset();       /* does the job */
 }
-#endif /* __USG */