From 6e2b44962ff86e9b654eca5bec38a1519f8b6bd7 Mon Sep 17 00:00:00 2001 From: eck Date: Mon, 18 Dec 1989 15:33:48 +0000 Subject: [PATCH] made a lot of changes --- lang/cem/libcc.ansi/time/.distr | 14 + lang/cem/libcc.ansi/time/LIST | 1 - lang/cem/libcc.ansi/time/Makefile | 22 ++ lang/cem/libcc.ansi/time/asctime.c | 4 +- lang/cem/libcc.ansi/time/clock.c | 74 ++++- lang/cem/libcc.ansi/time/difftime.c | 2 +- lang/cem/libcc.ansi/time/gmtime.c | 4 +- lang/cem/libcc.ansi/time/loc_incl.h | 14 +- lang/cem/libcc.ansi/time/localtime.c | 6 +- lang/cem/libcc.ansi/time/misc.c | 406 ++++++++++++++++++++++----- lang/cem/libcc.ansi/time/mktime.c | 125 ++++----- lang/cem/libcc.ansi/time/strftime.c | 22 +- lang/cem/libcc.ansi/time/time.c | 21 +- lang/cem/libcc.ansi/time/tzset.c | 7 +- 14 files changed, 549 insertions(+), 173 deletions(-) create mode 100644 lang/cem/libcc.ansi/time/.distr create mode 100644 lang/cem/libcc.ansi/time/Makefile diff --git a/lang/cem/libcc.ansi/time/.distr b/lang/cem/libcc.ansi/time/.distr new file mode 100644 index 000000000..bde041f82 --- /dev/null +++ b/lang/cem/libcc.ansi/time/.distr @@ -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 diff --git a/lang/cem/libcc.ansi/time/LIST b/lang/cem/libcc.ansi/time/LIST index a1c39e54b..6dfc5bb61 100644 --- a/lang/cem/libcc.ansi/time/LIST +++ b/lang/cem/libcc.ansi/time/LIST @@ -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 index 000000000..8d9360b5c --- /dev/null +++ b/lang/cem/libcc.ansi/time/Makefile @@ -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: diff --git a/lang/cem/libcc.ansi/time/asctime.c b/lang/cem/libcc.ansi/time/asctime.c index d0efa2536..80116246e 100644 --- a/lang/cem/libcc.ansi/time/asctime.c +++ b/lang/cem/libcc.ansi/time/asctime.c @@ -3,7 +3,6 @@ */ /* $Header$ */ -#include #include #include #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); diff --git a/lang/cem/libcc.ansi/time/clock.c b/lang/cem/libcc.ansi/time/clock.c index 06faa7eb0..2b9b08c05 100644 --- a/lang/cem/libcc.ansi/time/clock.c +++ b/lang/cem/libcc.ansi/time/clock.c @@ -4,16 +4,82 @@ /* $Header$ */ #include -#include -#include + +#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 } diff --git a/lang/cem/libcc.ansi/time/difftime.c b/lang/cem/libcc.ansi/time/difftime.c index c0de01481..6b1ba723e 100644 --- a/lang/cem/libcc.ansi/time/difftime.c +++ b/lang/cem/libcc.ansi/time/difftime.c @@ -1,5 +1,5 @@ /* - * difftime - compute the difference bnetween two calendar times + * difftime - compute the difference between two calendar times */ /* $Header$ */ diff --git a/lang/cem/libcc.ansi/time/gmtime.c b/lang/cem/libcc.ansi/time/gmtime.c index 07285d0ca..0d078cc81 100644 --- a/lang/cem/libcc.ansi/time/gmtime.c +++ b/lang/cem/libcc.ansi/time/gmtime.c @@ -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]) { diff --git a/lang/cem/libcc.ansi/time/loc_incl.h b/lang/cem/libcc.ansi/time/loc_incl.h index 3e72c545e..5ccbb4c5e 100644 --- a/lang/cem/libcc.ansi/time/loc_incl.h +++ b/lang/cem/libcc.ansi/time/loc_incl.h @@ -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]; diff --git a/lang/cem/libcc.ansi/time/localtime.c b/lang/cem/libcc.ansi/time/localtime.c index df90fd9d6..871bfdf52 100644 --- a/lang/cem/libcc.ansi/time/localtime.c +++ b/lang/cem/libcc.ansi/time/localtime.c @@ -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; diff --git a/lang/cem/libcc.ansi/time/misc.c b/lang/cem/libcc.ansi/time/misc.c index 557a12b4e..ec0b94511 100644 --- a/lang/cem/libcc.ansi/time/misc.c +++ b/lang/cem/libcc.ansi/time/misc.c @@ -3,101 +3,308 @@ */ /* $Header$ */ +#include #include #include #include -#ifdef __BSD4_2 -#include -#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_ydaytm_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; diff --git a/lang/cem/libcc.ansi/time/mktime.c b/lang/cem/libcc.ansi/time/mktime.c index ff83e0cea..597f104c7 100644 --- a/lang/cem/libcc.ansi/time/mktime.c +++ b/lang/cem/libcc.ansi/time/mktime.c @@ -7,16 +7,19 @@ #include #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; diff --git a/lang/cem/libcc.ansi/time/strftime.c b/lang/cem/libcc.ansi/time/strftime.c index 9827c6a1d..92f67b79b 100644 --- a/lang/cem/libcc.ansi/time/strftime.c +++ b/lang/cem/libcc.ansi/time/strftime.c @@ -6,7 +6,7 @@ #include #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 '%': diff --git a/lang/cem/libcc.ansi/time/time.c b/lang/cem/libcc.ansi/time/time.c index 4b8527889..ba816c4f4 100644 --- a/lang/cem/libcc.ansi/time/time.c +++ b/lang/cem/libcc.ansi/time/time.c @@ -3,17 +3,34 @@ */ /* $Header$ */ +#if defined(__BSD4_2) #include -#include +/* + * 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 diff --git a/lang/cem/libcc.ansi/time/tzset.c b/lang/cem/libcc.ansi/time/tzset.c index e1ae1f369..53d4dcb51 100644 --- a/lang/cem/libcc.ansi/time/tzset.c +++ b/lang/cem/libcc.ansi/time/tzset.c @@ -1,9 +1,9 @@ /* - * tzset - system V compatibility + * tzset - set timezone information */ /* $Header$ */ -#ifdef __USG +/* This function is present for System V && POSIX */ #include #include "loc_incl.h" @@ -11,6 +11,5 @@ void tzset(void) { - _tzone(); /* does the job */ + _tzset(); /* does the job */ } -#endif /* __USG */ -- 2.34.1