replace library time handling functions

mktime, tzset, asctime, ctime, gmtime, localtime, strftime
with zoneinfo implementations in src/commands/zoneinfo, referenced
from src/lib/stdtime/Makefile.in.
This commit is contained in:
Ben Gras 2007-03-30 15:36:49 +00:00
parent 6ccd37a982
commit 056ac0a0d3
13 changed files with 28 additions and 627 deletions

View file

@ -14,6 +14,11 @@ struct timeval
long /*useconds_t*/ tv_usec;
};
struct timezone {
int tz_minuteswest; /* minutes west of Greenwich */
int tz_dsttime; /* type of dst correction */
};
int gettimeofday(struct timeval *_RESTRICT tp, void *_RESTRICT tzp);
/* Compatibility with other Unix systems */

View file

@ -39,6 +39,8 @@ all-ack: makefiles
cd regex && $(MAKE) $@
mkdir -p obj-ack//./stdio
cd stdio && $(MAKE) $@
mkdir -p obj-ack//./stdtime
cd stdtime && $(MAKE) $@
mkdir -p obj-ack//./syscall
cd syscall && $(MAKE) $@
mkdir -p obj-ack//./syslib
@ -79,6 +81,8 @@ all-gnu: makefiles
cd regex && $(MAKE) $@
mkdir -p obj-gnu/./stdio
cd stdio && $(MAKE) $@
mkdir -p obj-gnu/./stdtime
cd stdtime && $(MAKE) $@
mkdir -p obj-gnu/./syscall
cd syscall && $(MAKE) $@
mkdir -p obj-gnu/./syslib
@ -108,6 +112,7 @@ clean depend depend-ack depend-gnu:: makefiles
cd posix && $(MAKE) $@
cd regex && $(MAKE) $@
cd stdio && $(MAKE) $@
cd stdtime && $(MAKE) $@
cd syscall && $(MAKE) $@
cd syslib && $(MAKE) $@
cd util && $(MAKE) $@
@ -128,6 +133,7 @@ makefiles: other/Makefile
makefiles: posix/Makefile
makefiles: regex/Makefile
makefiles: stdio/Makefile
makefiles: stdtime/Makefile
makefiles: syscall/Makefile
makefiles: syslib/Makefile
makefiles: util/Makefile
@ -159,6 +165,8 @@ regex/Makefile: regex/Makefile.in
cd regex && sh ../generate.sh ./regex ../obj-ack/ ../obj-gnu && $(MAKE) makefiles
stdio/Makefile: stdio/Makefile.in
cd stdio && sh ../generate.sh ./stdio ../obj-ack/ ../obj-gnu && $(MAKE) makefiles
stdtime/Makefile: stdtime/Makefile.in
cd stdtime && sh ../generate.sh ./stdtime ../obj-ack/ ../obj-gnu && $(MAKE) makefiles
syscall/Makefile: syscall/Makefile.in
cd syscall && sh ../generate.sh ./syscall ../obj-ack/ ../obj-gnu && $(MAKE) makefiles
syslib/Makefile: syslib/Makefile.in

View file

@ -17,6 +17,7 @@ SUBDIRS="ansi \
posix \
regex \
stdio \
stdtime \
syscall \
syslib \
util \

View file

@ -25,7 +25,6 @@ LIBRARIES=libc
libc_FILES=" \
abort.c \
abs.c \
asctime.c \
assert.c \
atexit.c \
atof.c \
@ -35,14 +34,12 @@ libc_FILES=" \
calloc.c \
chartab.c \
clock.c \
ctime.c \
difftime.c \
div.c \
errlist.c \
exit.c \
ext_comp.c \
getenv.c \
gmtime.c \
isalnum.c \
isalpha.c \
isascii.c \
@ -58,13 +55,11 @@ libc_FILES=" \
labs.c \
ldiv.c \
localeconv.c \
localtime.c \
malloc.c \
mblen.c \
mbstowcs.c \
mbtowc.c \
misc.c \
mktime.c \
qsort.c \
raise.c \
rand.c \
@ -74,7 +69,6 @@ libc_FILES=" \
strcoll.c \
strcspn.c \
strerror.c \
strftime.c \
strpbrk.c \
strspn.c \
strstr.c \
@ -84,7 +78,6 @@ libc_FILES=" \
system.c \
tolower.c \
toupper.c \
tzset.c \
wcstombs.c \
wctomb.c"

View file

@ -1,60 +0,0 @@
/*
* asctime - print a date
*/
/* $Header$ */
#include <string.h>
#include <time.h>
#include "loc_time.h"
#define DATE_STR "??? ??? ?? ??:??:?? ????\n"
static char *
two_digits(register char *pb, int i, int nospace)
{
*pb = (i / 10) % 10 + '0';
if (!nospace && *pb == '0') *pb = ' ';
pb++;
*pb++ = (i % 10) + '0';
return ++pb;
}
static char *
four_digits(register char *pb, int i)
{
i %= 10000;
*pb++ = (i / 1000) + '0';
i %= 1000;
*pb++ = (i / 100) + '0';
i %= 100;
*pb++ = (i / 10) + '0';
*pb++ = (i % 10) + '0';
return ++pb;
}
char *asctime(const struct tm *timeptr)
{
static char buf[26];
register char *pb = buf;
register const char *ps;
register int n;
strcpy(pb, DATE_STR);
ps = _days[timeptr->tm_wday];
n = ABB_LEN;
while(--n >= 0) *pb++ = *ps++;
pb++;
ps = _months[timeptr->tm_mon];
n = ABB_LEN;
while(--n >= 0) *pb++ = *ps++;
pb++;
pb = two_digits(
two_digits(
two_digits(two_digits(pb, timeptr->tm_mday, 0)
, timeptr->tm_hour, 1)
, timeptr->tm_min, 1)
, timeptr->tm_sec, 1);
four_digits(pb, timeptr->tm_year + 1900);
return buf;
}

View file

@ -1,12 +0,0 @@
/*
* ctime - convers the calendar time to a string
*/
/* $Header$ */
#include <time.h>
char *
ctime(const time_t *timer)
{
return asctime(localtime(timer));
}

View file

@ -1,41 +0,0 @@
/*
* gmtime - convert the calendar time into broken down time
*/
/* $Header$ */
#include <time.h>
#include <limits.h>
#include "loc_time.h"
struct tm *
gmtime(register const time_t *timer)
{
static struct tm br_time;
register struct tm *timep = &br_time;
time_t time = *timer;
register unsigned long dayclock, dayno;
int year = EPOCH_YR;
dayclock = (unsigned long)time % SECS_DAY;
dayno = (unsigned long)time / SECS_DAY;
timep->tm_sec = dayclock % 60;
timep->tm_min = (dayclock % 3600) / 60;
timep->tm_hour = dayclock / 3600;
timep->tm_wday = (dayno + 4) % 7; /* day 0 was a thursday */
while (dayno >= YEARSIZE(year)) {
dayno -= YEARSIZE(year);
year++;
}
timep->tm_year = year - YEAR0;
timep->tm_yday = dayno;
timep->tm_mon = 0;
while (dayno >= _ytab[LEAPYEAR(year)][timep->tm_mon]) {
dayno -= _ytab[LEAPYEAR(year)][timep->tm_mon];
timep->tm_mon++;
}
timep->tm_mday = dayno + 1;
timep->tm_isdst = 0;
return timep;
}

View file

@ -1,34 +0,0 @@
/*
* localtime - convert a calendar time into broken down time
*/
/* $Header$ */
#include <time.h>
#include "loc_time.h"
/* We must be careful, since an int can't represent all the seconds in a day.
* Hence the adjustment of minutes when adding timezone and dst information.
* This assumes that both must be expressable in multiples of a minute.
* Furthermore, it is assumed that both fit into an integer when expressed as
* minutes (this is about 22 days, so this should not cause any problems).
*/
struct tm *
localtime(const time_t *timer)
{
struct tm *timep;
unsigned dst;
_tzset();
timep = gmtime(timer); /* tm->tm_isdst == 0 */
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;
}

View file

@ -49,10 +49,8 @@ static char dststr[TZ_LEN + 1] = "GDT"; /* string for daylight saving */
long _timezone = 0;
long _dst_off = 60 * 60;
int _daylight = 0;
char *_tzname[2] = {ntstr, dststr};
#if defined(__USG) || defined(_POSIX_SOURCE)
char *tzname[2] = {ntstr, dststr};
#if defined(__USG)
long timezone = 0;
@ -219,106 +217,6 @@ parseRule(register char *buf, register const char *p)
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)
{
long tz, dst = 60 * 60, sign = 1;
static char lastTZ[2 * RULE_LEN];
static char buffer[RULE_LEN];
if (!p) return;
if (*p == ':') {
/*
* According to POSIX, this is implementation defined.
* Since it depends on the particular operating system, we
* can do nothing.
*/
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)
struct timeval tv;
struct timezone tz;
_gettimeofday(&tv, &tz);
_daylight = tz.tz_dsttime;
_timezone = tz.tz_minuteswest * 60L;
#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;
#endif
#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
#endif /* __USG || _POSIX_SOURCE */
}
static int
last_sunday(register int day, register struct tm *timep)
{
@ -356,55 +254,3 @@ date_of(register struct dsttype *dst, struct tm *timep)
return day;
}
/*
* The default dst transitions are those for Western Europe (except Great
* Britain).
*/
unsigned
_dstget(register struct tm *timep)
{
int begindst, enddst;
register struct dsttype *dsts = &dststart, *dste = &dstend;
int do_dst = 0;
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)
do_dst = 1;
} else { /* southern hemisphere */
if (timep->tm_yday > begindst || timep->tm_yday < enddst)
do_dst = 1;
}
if (!do_dst
&& (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) * 60L
+ timep->tm_sec;
if ((timep->tm_yday == begindst && cursec >= dsttranssec)
|| (timep->tm_yday == enddst && cursec < dsttranssec))
do_dst = 1;
}
if (do_dst) return _dst_off;
timep->tm_isdst = 0;
return 0;
}

View file

@ -1,132 +0,0 @@
/*
* mktime - convert local time into calendar time
*/
/* $Header$ */
/* Michael A. Temari <temari@ix.netcom.com> 03/01/96 */
/* - fixed bug is structure fixup code */
#include <time.h>
#include <limits.h>
#include "loc_time.h"
/* The code assumes that unsigned long can be converted to time_t.
* A time_t should not be wider than unsigned long, since this would mean
* that the check for overflow at the end could fail.
*/
time_t
mktime(register struct tm *timep)
{
register long day, year;
register int tm_year;
int yday, month;
register unsigned long seconds;
int overflow;
unsigned dst;
timep->tm_min += timep->tm_sec / 60;
timep->tm_sec %= 60;
if (timep->tm_sec < 0) {
timep->tm_sec += 60;
timep->tm_min--;
}
timep->tm_hour += timep->tm_min / 60;
timep->tm_min = timep->tm_min % 60;
if (timep->tm_min < 0) {
timep->tm_min += 60;
timep->tm_hour--;
}
day = timep->tm_hour / 24;
timep->tm_hour= timep->tm_hour % 24;
if (timep->tm_hour < 0) {
timep->tm_hour += 24;
day--;
}
timep->tm_year += timep->tm_mon / 12;
timep->tm_mon %= 12;
if (timep->tm_mon < 0) {
timep->tm_mon += 12;
timep->tm_year--;
}
day += (timep->tm_mday - 1);
while (day < 0) {
if(--timep->tm_mon < 0) {
timep->tm_year--;
timep->tm_mon = 11;
}
day += _ytab[LEAPYEAR(YEAR0 + 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;
_tzset(); /* set timezone and dst info */
year = EPOCH_YR;
if (timep->tm_year < year - YEAR0) return (time_t)-1;
seconds = 0;
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 (month < timep->tm_mon) {
yday += _ytab[LEAPYEAR(tm_year)][month];
month++;
}
yday += (timep->tm_mday - 1);
if (day + yday < 0) overflow++;
day += yday;
timep->tm_yday = yday;
timep->tm_wday = (day + 4) % 7; /* day 0 was thursday (4) */
seconds = ((timep->tm_hour * 60L) + timep->tm_min) * 60L + timep->tm_sec;
if ((TIME_MAX - seconds) / SECS_DAY < day) overflow++;
seconds += day * SECS_DAY;
/* Now adjust according to timezone and daylight saving time */
if (((_timezone > 0) && (TIME_MAX - _timezone < seconds))
|| ((_timezone < 0) && (seconds < -_timezone)))
overflow++;
seconds += _timezone;
if (timep->tm_isdst < 0)
dst = _dstget(timep);
else if (timep->tm_isdst)
dst = _dst_off;
else dst = 0;
if (dst > seconds) overflow++; /* dst is always non-negative */
seconds -= dst;
if (overflow) return (time_t)-1;
if ((time_t)seconds != seconds) return (time_t)-1;
return (time_t)seconds;
}

View file

@ -1,172 +0,0 @@
/*
* strftime - convert a structure to a string, controlled by an argument
*/
/* $Header$ */
#include <time.h>
#include "loc_time.h"
/* 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 *
s_prnt(char *s, size_t maxsize, const char *str, int width)
{
while (width > 0 || (width < 0 && *str)) {
if (!maxsize) break;
*s++ = *str++;
maxsize--;
width--;
}
return s;
}
static char *
u_prnt(char *s, size_t maxsize, unsigned val, int width)
{
int c;
c = val % 10;
val = val / 10;
if (--width > 0 || (width < 0 && val != 0))
s = u_prnt(s, (maxsize ? maxsize - 1 : 0), val, width);
if (maxsize) *s++ = c + '0';
return s;
}
size_t
strftime(char *s, size_t maxsize,
const char *format, const struct tm *timeptr)
{
size_t n;
char *firsts, *olds;
if (!format) return 0;
_tzset(); /* for %Z conversion */
firsts = s;
while (maxsize && *format) {
while (maxsize && *format && *format != '%') {
*s++ = *format++;
maxsize--;
}
if (!maxsize || !*format) break;
format++;
olds = s;
switch (*format++) {
case 'a':
s = s_prnt(s, maxsize,
_days[timeptr->tm_wday], ABB_LEN);
maxsize -= s - olds;
break;
case 'A':
s = s_prnt(s, maxsize, _days[timeptr->tm_wday], -1);
maxsize -= s - olds;
break;
case 'b':
s = s_prnt(s, maxsize,
_months[timeptr->tm_mon], ABB_LEN);
maxsize -= s - olds;
break;
case 'B':
s = s_prnt(s, maxsize, _months[timeptr->tm_mon], -1);
maxsize -= s - olds;
break;
case 'c':
n = strftime(s, maxsize,
"%a %b %d %H:%M:%S %Y", timeptr);
if (n) maxsize -= n;
else maxsize = 0;
s += n;
break;
case 'd':
s = u_prnt(s, maxsize, timeptr->tm_mday, 2);
maxsize -= s - olds;
break;
case 'H':
s = u_prnt(s, maxsize, timeptr->tm_hour, 2);
maxsize -= s - olds;
break;
case 'I':
s = u_prnt(s, maxsize,
(timeptr->tm_hour + 11) % 12 + 1, 2);
maxsize -= s - olds;
break;
case 'j':
s = u_prnt(s, maxsize, timeptr->tm_yday + 1, 3);
maxsize -= s - olds;
break;
case 'm':
s = u_prnt(s, maxsize, timeptr->tm_mon + 1, 2);
maxsize -= s - olds;
break;
case 'M':
s = u_prnt(s, maxsize, timeptr->tm_min, 2);
maxsize -= s - olds;
break;
case 'p':
s = s_prnt(s, maxsize,
(timeptr->tm_hour < 12) ? "AM" : "PM", 2);
maxsize -= s - olds;
break;
case 'S':
s = u_prnt(s, maxsize, timeptr->tm_sec, 2);
maxsize -= s - olds;
break;
case 'U':
s = u_prnt(s, maxsize, /* ??? */
(timeptr->tm_yday + 7 - timeptr->tm_wday) / 7, 2);
maxsize -= s - olds;
break;
case 'w':
s = u_prnt(s, maxsize, timeptr->tm_wday, 1);
maxsize -= s - olds;
break;
case 'W':
s = u_prnt(s, maxsize, /* ??? */
(timeptr->tm_yday+7-(timeptr->tm_wday+6)%7)/7,2);
maxsize -= s - olds;
break;
case 'x':
n = strftime(s, maxsize, "%a %b %d %Y", timeptr);
if (n) maxsize -= n;
else maxsize = 0;
s += n;
break;
case 'X':
n = strftime(s, maxsize, "%H:%M:%S", timeptr);
if (n) maxsize -= n;
else maxsize = 0;
s += n;
break;
case 'y':
s = u_prnt(s, maxsize, timeptr->tm_year % 100, 2);
maxsize -= s - olds;
break;
case 'Y':
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);
maxsize -= s - olds;
break;
case '%':
*s++ = '%';
maxsize--;
break;
default:
/* A conversion error. Leave the loop. */
while (*format) format++;
break;
}
}
if (maxsize) {
*s = '\0';
return s - firsts;
}
return 0; /* The buffer is full */
}

View file

@ -1,15 +0,0 @@
/*
* tzset - set timezone information
*/
/* $Header$ */
/* This function is present for System V && POSIX */
#include <time.h>
#include "loc_time.h"
void
tzset(void)
{
_tzset(); /* does the job */
}

14
lib/stdtime/Makefile.in Normal file
View file

@ -0,0 +1,14 @@
# Makefile for lib/stdtime.
Z=../../commands/zoneinfo
CFLAGS="-O -D_MINIX -D_POSIX_SOURCE -D__USG -I$Z"
LIBRARIES=libc
libc_FILES="
$Z/asctime.c
$Z/localtime.c
$Z/strftime.c
"
TYPE=both