mirror of
https://github.com/opnsense/src.git
synced 2026-05-28 04:12:45 -04:00
Import the 96h release of ADO's timezone code. This release is
primarily bugfixes, but is also contains a disclaimer of copyright. As we are completely off the vendor branch here, this import has no effect on the source tree.
This commit is contained in:
parent
89e2ea2b0f
commit
979a211643
6 changed files with 813 additions and 425 deletions
|
|
@ -1,6 +1,11 @@
|
|||
/*
|
||||
** This file is in the public domain, so clarified as of
|
||||
** June 5, 1996 by Arthur David Olson (arthur_david_olson@nih.gov).
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
#ifndef NOID
|
||||
static char elsieid[] = "@(#)asctime.c 7.5";
|
||||
static char elsieid[] = "@(#)asctime.c 7.7";
|
||||
#endif /* !defined NOID */
|
||||
#endif /* !defined lint */
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,11 @@
|
|||
/*
|
||||
** This file is in the public domain, so clarified as of
|
||||
** June 5, 1996 by Arthur David Olson (arthur_david_olson@nih.gov).
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
#ifndef NOID
|
||||
static char elsieid[] = "@(#)difftime.c 7.4";
|
||||
static char elsieid[] = "@(#)difftime.c 7.7";
|
||||
#endif /* !defined NOID */
|
||||
#endif /* !defined lint */
|
||||
|
||||
|
|
@ -43,9 +48,7 @@ const time_t time0;
|
|||
/*
|
||||
** Repair delta overflow.
|
||||
*/
|
||||
hibit = 1;
|
||||
while ((hibit <<= 1) > 0)
|
||||
continue;
|
||||
hibit = (~ (time_t) 0) << (TYPE_BIT(time_t) - 1);
|
||||
/*
|
||||
** The following expression rounds twice, which means
|
||||
** the result may not be the closest to the true answer.
|
||||
|
|
@ -65,10 +68,10 @@ const time_t time0;
|
|||
** This problem occurs only with very large differences.
|
||||
** It's too painful to fix this portably.
|
||||
** We are not alone in this problem;
|
||||
** many C compilers round twice when converting
|
||||
** some C compilers round twice when converting
|
||||
** large unsigned types to small floating types,
|
||||
** so if time_t is unsigned the "return delta" above
|
||||
** has the same double-rounding problem.
|
||||
** has the same double-rounding problem with those compilers.
|
||||
*/
|
||||
return delta - 2 * (long_double) hibit;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,11 @@
|
|||
/*
|
||||
** This file is in the public domain, so clarified as of
|
||||
** June 5, 1996 by Arthur David Olson (arthur_david_olson@nih.gov).
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
#ifndef NOID
|
||||
static char elsieid[] = "@(#)localtime.c 7.19";
|
||||
static char elsieid[] = "@(#)localtime.c 7.57";
|
||||
#endif /* !defined NOID */
|
||||
#endif /* !defined lint */
|
||||
|
||||
|
|
@ -16,7 +21,9 @@ static char elsieid[] = "@(#)localtime.c 7.19";
|
|||
#include "tzfile.h"
|
||||
#include "fcntl.h"
|
||||
|
||||
#define ACCESS_MODE O_RDONLY
|
||||
/*
|
||||
** SunOS 4.1.1 headers lack O_BINARY.
|
||||
*/
|
||||
|
||||
#ifdef O_BINARY
|
||||
#define OPEN_MODE (O_RDONLY | O_BINARY)
|
||||
|
|
@ -29,9 +36,9 @@ static char elsieid[] = "@(#)localtime.c 7.19";
|
|||
/*
|
||||
** Someone might make incorrect use of a time zone abbreviation:
|
||||
** 1. They might reference tzname[0] before calling tzset (explicitly
|
||||
** or implicitly).
|
||||
** or implicitly).
|
||||
** 2. They might reference tzname[1] before calling tzset (explicitly
|
||||
** or implicitly).
|
||||
** or implicitly).
|
||||
** 3. They might reference tzname[1] after setting to a time zone
|
||||
** in which Daylight Saving Time is never observed.
|
||||
** 4. They might reference tzname[0] after setting to a time zone
|
||||
|
|
@ -48,13 +55,16 @@ static char elsieid[] = "@(#)localtime.c 7.19";
|
|||
#define WILDABBR " "
|
||||
#endif /* !defined WILDABBR */
|
||||
|
||||
static const char GMT[] = "GMT";
|
||||
static char wildabbr[] = "WILDABBR";
|
||||
|
||||
static const char gmt[] = "GMT";
|
||||
|
||||
struct ttinfo { /* time type information */
|
||||
long tt_gmtoff; /* GMT offset in seconds */
|
||||
int tt_isdst; /* used to set tm_isdst */
|
||||
int tt_abbrind; /* abbreviation list index */
|
||||
int tt_ttisstd; /* TRUE if transition is std time */
|
||||
int tt_ttisgmt; /* TRUE if transition is GMT */
|
||||
};
|
||||
|
||||
struct lsinfo { /* leap second information */
|
||||
|
|
@ -79,7 +89,7 @@ struct state {
|
|||
time_t ats[TZ_MAX_TIMES];
|
||||
unsigned char types[TZ_MAX_TIMES];
|
||||
struct ttinfo ttis[TZ_MAX_TYPES];
|
||||
char chars[BIGGEST(BIGGEST(TZ_MAX_CHARS + 1, sizeof GMT),
|
||||
char chars[BIGGEST(BIGGEST(TZ_MAX_CHARS + 1, sizeof gmt),
|
||||
(2 * (MY_TZNAME_MAX + 1)))];
|
||||
struct lsinfo lsis[TZ_MAX_LEAPS];
|
||||
};
|
||||
|
|
@ -116,9 +126,13 @@ static int increment_overflow P((int * number, int delta));
|
|||
static int normalize_overflow P((int * tensptr, int * unitsptr,
|
||||
int base));
|
||||
static void settzname P((void));
|
||||
static time_t time1 P((struct tm * tmp, void (* funcp)(),
|
||||
static time_t time1 P((struct tm * tmp,
|
||||
void(*funcp) P((const time_t *,
|
||||
long, struct tm *)),
|
||||
long offset));
|
||||
static time_t time2 P((struct tm *tmp, void (* funcp)(),
|
||||
static time_t time2 P((struct tm *tmp,
|
||||
void(*funcp) P((const time_t *,
|
||||
long, struct tm*)),
|
||||
long offset, int * okayp));
|
||||
static void timesub P((const time_t * timep, long offset,
|
||||
const struct state * sp, struct tm * tmp));
|
||||
|
|
@ -142,14 +156,29 @@ static struct state gmtmem;
|
|||
#define gmtptr (&gmtmem)
|
||||
#endif /* State Farm */
|
||||
|
||||
#ifndef TZ_STRLEN_MAX
|
||||
#define TZ_STRLEN_MAX 255
|
||||
#endif /* !defined TZ_STRLEN_MAX */
|
||||
|
||||
static char lcl_TZname[TZ_STRLEN_MAX + 1];
|
||||
static int lcl_is_set;
|
||||
static int gmt_is_set;
|
||||
|
||||
char * tzname[2] = {
|
||||
WILDABBR,
|
||||
WILDABBR
|
||||
wildabbr,
|
||||
wildabbr
|
||||
};
|
||||
|
||||
/*
|
||||
** Section 4.12.3 of X3.159-1989 requires that
|
||||
** Except for the strftime function, these functions [asctime,
|
||||
** ctime, gmtime, localtime] return values in one of two static
|
||||
** objects: a broken-down time structure and an array of char.
|
||||
** Thanks to Paul Eggert (eggert@twinsun.com) for noting this.
|
||||
*/
|
||||
|
||||
static struct tm tm;
|
||||
|
||||
#ifdef USG_COMPAT
|
||||
time_t timezone = 0;
|
||||
int daylight = 0;
|
||||
|
|
@ -166,20 +195,20 @@ const char * const codep;
|
|||
register long result;
|
||||
register int i;
|
||||
|
||||
result = 0;
|
||||
result = (codep[0] & 0x80) ? ~0L : 0L;
|
||||
for (i = 0; i < 4; ++i)
|
||||
result = (result << 8) | (codep[i] & 0xff);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
settzname()
|
||||
settzname P((void))
|
||||
{
|
||||
register const struct state * const sp = lclptr;
|
||||
register int i;
|
||||
register struct state * const sp = lclptr;
|
||||
register int i;
|
||||
|
||||
tzname[0] = WILDABBR;
|
||||
tzname[1] = WILDABBR;
|
||||
tzname[0] = wildabbr;
|
||||
tzname[1] = wildabbr;
|
||||
#ifdef USG_COMPAT
|
||||
daylight = 0;
|
||||
timezone = 0;
|
||||
|
|
@ -189,7 +218,7 @@ settzname()
|
|||
#endif /* defined ALTZONE */
|
||||
#ifdef ALL_STATE
|
||||
if (sp == NULL) {
|
||||
tzname[0] = tzname[1] = GMT;
|
||||
tzname[0] = tzname[1] = gmt;
|
||||
return;
|
||||
}
|
||||
#endif /* defined ALL_STATE */
|
||||
|
|
@ -197,7 +226,7 @@ settzname()
|
|||
register const struct ttinfo * const ttisp = &sp->ttis[i];
|
||||
|
||||
tzname[ttisp->tt_isdst] =
|
||||
(char *) &sp->chars[ttisp->tt_abbrind];
|
||||
&sp->chars[ttisp->tt_abbrind];
|
||||
#ifdef USG_COMPAT
|
||||
if (ttisp->tt_isdst)
|
||||
daylight = 1;
|
||||
|
|
@ -218,7 +247,7 @@ settzname()
|
|||
sp->types[i]];
|
||||
|
||||
tzname[ttisp->tt_isdst] =
|
||||
(char *) &sp->chars[ttisp->tt_abbrind];
|
||||
&sp->chars[ttisp->tt_abbrind];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -234,7 +263,14 @@ register struct state * const sp;
|
|||
if (name == NULL && (name = TZDEFAULT) == NULL)
|
||||
return -1;
|
||||
{
|
||||
register int doaccess;
|
||||
register int doaccess;
|
||||
/*
|
||||
** Section 4.9.1 of the C standard says that
|
||||
** "FILENAME_MAX expands to an integral constant expression
|
||||
** that is the sie needed for an array of char large enough
|
||||
** to hold the longest file name string that the implementation
|
||||
** guarantees can be opened."
|
||||
*/
|
||||
char fullname[FILENAME_MAX + 1];
|
||||
|
||||
if (name[0] == ':')
|
||||
|
|
@ -255,39 +291,49 @@ register struct state * const sp;
|
|||
doaccess = TRUE;
|
||||
name = fullname;
|
||||
}
|
||||
if (doaccess && access(name, ACCESS_MODE) != 0)
|
||||
if (doaccess && access(name, R_OK) != 0)
|
||||
return -1;
|
||||
if ((fid = open(name, OPEN_MODE)) == -1)
|
||||
return -1;
|
||||
}
|
||||
{
|
||||
register const struct tzhead * tzhp;
|
||||
char buf[sizeof *sp + sizeof *tzhp];
|
||||
int ttisstdcnt;
|
||||
struct tzhead * tzhp;
|
||||
char buf[sizeof *sp + sizeof *tzhp];
|
||||
int ttisstdcnt;
|
||||
int ttisgmtcnt;
|
||||
|
||||
i = read(fid, buf, sizeof buf);
|
||||
if (close(fid) != 0 || i < sizeof *tzhp)
|
||||
if (close(fid) != 0)
|
||||
return -1;
|
||||
tzhp = (struct tzhead *) buf;
|
||||
ttisstdcnt = (int) detzcode(tzhp->tzh_ttisstdcnt);
|
||||
sp->leapcnt = (int) detzcode(tzhp->tzh_leapcnt);
|
||||
sp->timecnt = (int) detzcode(tzhp->tzh_timecnt);
|
||||
sp->typecnt = (int) detzcode(tzhp->tzh_typecnt);
|
||||
sp->charcnt = (int) detzcode(tzhp->tzh_charcnt);
|
||||
p = buf;
|
||||
p += sizeof tzhp->tzh_reserved;
|
||||
ttisstdcnt = (int) detzcode(p);
|
||||
p += 4;
|
||||
ttisgmtcnt = (int) detzcode(p);
|
||||
p += 4;
|
||||
sp->leapcnt = (int) detzcode(p);
|
||||
p += 4;
|
||||
sp->timecnt = (int) detzcode(p);
|
||||
p += 4;
|
||||
sp->typecnt = (int) detzcode(p);
|
||||
p += 4;
|
||||
sp->charcnt = (int) detzcode(p);
|
||||
p += 4;
|
||||
if (sp->leapcnt < 0 || sp->leapcnt > TZ_MAX_LEAPS ||
|
||||
sp->typecnt <= 0 || sp->typecnt > TZ_MAX_TYPES ||
|
||||
sp->timecnt < 0 || sp->timecnt > TZ_MAX_TIMES ||
|
||||
sp->charcnt < 0 || sp->charcnt > TZ_MAX_CHARS ||
|
||||
(ttisstdcnt != sp->typecnt && ttisstdcnt != 0))
|
||||
(ttisstdcnt != sp->typecnt && ttisstdcnt != 0) ||
|
||||
(ttisgmtcnt != sp->typecnt && ttisgmtcnt != 0))
|
||||
return -1;
|
||||
if (i < sizeof *tzhp +
|
||||
sp->timecnt * (4 + sizeof (char)) +
|
||||
sp->typecnt * (4 + 2 * sizeof (char)) +
|
||||
sp->charcnt * sizeof (char) +
|
||||
sp->leapcnt * 2 * 4 +
|
||||
ttisstdcnt * sizeof (char))
|
||||
if (i - (p - buf) < sp->timecnt * 4 + /* ats */
|
||||
sp->timecnt + /* types */
|
||||
sp->typecnt * (4 + 2) + /* ttinfos */
|
||||
sp->charcnt + /* chars */
|
||||
sp->leapcnt * (4 + 4) + /* lsinfos */
|
||||
ttisstdcnt + /* ttisstds */
|
||||
ttisgmtcnt) /* ttisgmts */
|
||||
return -1;
|
||||
p = buf + sizeof *tzhp;
|
||||
for (i = 0; i < sp->timecnt; ++i) {
|
||||
sp->ats[i] = detzcode(p);
|
||||
p += 4;
|
||||
|
|
@ -336,6 +382,19 @@ register struct state * const sp;
|
|||
return -1;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < sp->typecnt; ++i) {
|
||||
register struct ttinfo * ttisp;
|
||||
|
||||
ttisp = &sp->ttis[i];
|
||||
if (ttisgmtcnt == 0)
|
||||
ttisp->tt_ttisgmt = FALSE;
|
||||
else {
|
||||
ttisp->tt_ttisgmt = *p++;
|
||||
if (ttisp->tt_ttisgmt != TRUE &&
|
||||
ttisp->tt_ttisgmt != FALSE)
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -361,7 +420,7 @@ register const char * strp;
|
|||
{
|
||||
register char c;
|
||||
|
||||
while ((c = *strp) != '\0' && !isdigit(c) && c != ',' && c != '-' &&
|
||||
while ((c = *strp) != '\0' && !is_digit(c) && c != ',' && c != '-' &&
|
||||
c != '+')
|
||||
++strp;
|
||||
return strp;
|
||||
|
|
@ -384,15 +443,15 @@ const int max;
|
|||
register char c;
|
||||
register int num;
|
||||
|
||||
if (strp == NULL || !isdigit(*strp))
|
||||
if (strp == NULL || !is_digit(c = *strp))
|
||||
return NULL;
|
||||
num = 0;
|
||||
while ((c = *strp) != '\0' && isdigit(c)) {
|
||||
do {
|
||||
num = num * 10 + (c - '0');
|
||||
if (num > max)
|
||||
return NULL; /* illegal value */
|
||||
++strp;
|
||||
}
|
||||
c = *++strp;
|
||||
} while (is_digit(c));
|
||||
if (num < min)
|
||||
return NULL; /* illegal value */
|
||||
*nump = num;
|
||||
|
|
@ -414,10 +473,16 @@ long * const secsp;
|
|||
{
|
||||
int num;
|
||||
|
||||
strp = getnum(strp, &num, 0, HOURSPERDAY);
|
||||
/*
|
||||
** `HOURSPERDAY * DAYSPERWEEK - 1' allows quasi-Posix rules like
|
||||
** "M10.4.6/26", which does not conform to Posix,
|
||||
** but which specifies the equivalent of
|
||||
** ``02:00 on the first Sunday on or after 23 Oct''.
|
||||
*/
|
||||
strp = getnum(strp, &num, 0, HOURSPERDAY * DAYSPERWEEK - 1);
|
||||
if (strp == NULL)
|
||||
return NULL;
|
||||
*secsp = num * SECSPERHOUR;
|
||||
*secsp = num * (long) SECSPERHOUR;
|
||||
if (*strp == ':') {
|
||||
++strp;
|
||||
strp = getnum(strp, &num, 0, MINSPERHOUR - 1);
|
||||
|
|
@ -426,7 +491,8 @@ long * const secsp;
|
|||
*secsp += num * SECSPERMIN;
|
||||
if (*strp == ':') {
|
||||
++strp;
|
||||
strp = getnum(strp, &num, 0, SECSPERMIN - 1);
|
||||
/* `SECSPERMIN' allows for leap seconds. */
|
||||
strp = getnum(strp, &num, 0, SECSPERMIN);
|
||||
if (strp == NULL)
|
||||
return NULL;
|
||||
*secsp += num;
|
||||
|
|
@ -447,14 +513,13 @@ getoffset(strp, offsetp)
|
|||
register const char * strp;
|
||||
long * const offsetp;
|
||||
{
|
||||
register int neg;
|
||||
register int neg = 0;
|
||||
|
||||
if (*strp == '-') {
|
||||
neg = 1;
|
||||
++strp;
|
||||
} else if (isdigit(*strp) || *strp++ == '+')
|
||||
neg = 0;
|
||||
else return NULL; /* illegal offset */
|
||||
} else if (*strp == '+')
|
||||
++strp;
|
||||
strp = getsecs(strp, offsetp);
|
||||
if (strp == NULL)
|
||||
return NULL; /* illegal time */
|
||||
|
|
@ -499,7 +564,7 @@ register struct rule * const rulep;
|
|||
if (*strp++ != '.')
|
||||
return NULL;
|
||||
strp = getnum(strp, &rulep->r_day, 0, DAYSPERWEEK - 1);
|
||||
} else if (isdigit(*strp)) {
|
||||
} else if (is_digit(*strp)) {
|
||||
/*
|
||||
** Day of year.
|
||||
*/
|
||||
|
|
@ -536,6 +601,7 @@ const long offset;
|
|||
register int i;
|
||||
int d, m1, yy0, yy1, yy2, dow;
|
||||
|
||||
INITIALIZE(value);
|
||||
leapyear = isleap(year);
|
||||
switch (rulep->r_type) {
|
||||
|
||||
|
|
@ -626,8 +692,8 @@ const int lastditch;
|
|||
{
|
||||
const char * stdname;
|
||||
const char * dstname;
|
||||
int stdlen;
|
||||
int dstlen;
|
||||
size_t stdlen;
|
||||
size_t dstlen;
|
||||
long stdoffset;
|
||||
long dstoffset;
|
||||
register time_t * atp;
|
||||
|
|
@ -635,6 +701,7 @@ const int lastditch;
|
|||
register char * cp;
|
||||
register int load_result;
|
||||
|
||||
INITIALIZE(dstname);
|
||||
stdname = name;
|
||||
if (lastditch) {
|
||||
stdlen = strlen(name); /* length of standard zone name */
|
||||
|
|
@ -721,82 +788,90 @@ const int lastditch;
|
|||
SECSPERDAY;
|
||||
}
|
||||
} else {
|
||||
int sawstd;
|
||||
int sawdst;
|
||||
long stdfix;
|
||||
long dstfix;
|
||||
long oldfix;
|
||||
int isdst;
|
||||
register long theirstdoffset;
|
||||
register long theirdstoffset;
|
||||
register long theiroffset;
|
||||
register int isdst;
|
||||
register int i;
|
||||
register int j;
|
||||
|
||||
if (*name != '\0')
|
||||
return -1;
|
||||
if (load_result != 0)
|
||||
return -1;
|
||||
/*
|
||||
** Compute the difference between the real and
|
||||
** prototype standard and summer time offsets
|
||||
** from GMT, and put the real standard and summer
|
||||
** time offsets into the rules in place of the
|
||||
** prototype offsets.
|
||||
** Initial values of theirstdoffset and theirdstoffset.
|
||||
*/
|
||||
sawstd = FALSE;
|
||||
sawdst = FALSE;
|
||||
stdfix = 0;
|
||||
dstfix = 0;
|
||||
for (i = 0; i < sp->typecnt; ++i) {
|
||||
if (sp->ttis[i].tt_isdst) {
|
||||
oldfix = dstfix;
|
||||
dstfix = sp->ttis[i].tt_gmtoff +
|
||||
dstoffset;
|
||||
if (sawdst && (oldfix != dstfix))
|
||||
return -1;
|
||||
sp->ttis[i].tt_gmtoff = -dstoffset;
|
||||
sp->ttis[i].tt_abbrind = stdlen + 1;
|
||||
sawdst = TRUE;
|
||||
} else {
|
||||
oldfix = stdfix;
|
||||
stdfix = sp->ttis[i].tt_gmtoff +
|
||||
stdoffset;
|
||||
if (sawstd && (oldfix != stdfix))
|
||||
return -1;
|
||||
sp->ttis[i].tt_gmtoff = -stdoffset;
|
||||
sp->ttis[i].tt_abbrind = 0;
|
||||
sawstd = TRUE;
|
||||
theirstdoffset = 0;
|
||||
for (i = 0; i < sp->timecnt; ++i) {
|
||||
j = sp->types[i];
|
||||
if (!sp->ttis[j].tt_isdst) {
|
||||
theirstdoffset =
|
||||
-sp->ttis[j].tt_gmtoff;
|
||||
break;
|
||||
}
|
||||
}
|
||||
theirdstoffset = 0;
|
||||
for (i = 0; i < sp->timecnt; ++i) {
|
||||
j = sp->types[i];
|
||||
if (sp->ttis[j].tt_isdst) {
|
||||
theirdstoffset =
|
||||
-sp->ttis[j].tt_gmtoff;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/*
|
||||
** Make sure we have both standard and summer time.
|
||||
** Initially we're assumed to be in standard time.
|
||||
*/
|
||||
if (!sawdst || !sawstd)
|
||||
return -1;
|
||||
isdst = FALSE;
|
||||
theiroffset = theirstdoffset;
|
||||
/*
|
||||
** Now correct the transition times by shifting
|
||||
** them by the difference between the real and
|
||||
** prototype offsets. Note that this difference
|
||||
** can be different in standard and summer time;
|
||||
** the prototype probably has a 1-hour difference
|
||||
** between standard and summer time, but a different
|
||||
** difference can be specified in TZ.
|
||||
** Now juggle transition times and types
|
||||
** tracking offsets as you do.
|
||||
*/
|
||||
isdst = FALSE; /* we start in standard time */
|
||||
for (i = 0; i < sp->timecnt; ++i) {
|
||||
register const struct ttinfo * ttisp;
|
||||
|
||||
/*
|
||||
** If summer time is in effect, and the
|
||||
** transition time was not specified as
|
||||
** standard time, add the summer time
|
||||
** offset to the transition time;
|
||||
** otherwise, add the standard time offset
|
||||
** to the transition time.
|
||||
*/
|
||||
ttisp = &sp->ttis[sp->types[i]];
|
||||
sp->ats[i] +=
|
||||
(isdst && !ttisp->tt_ttisstd) ?
|
||||
dstfix : stdfix;
|
||||
isdst = ttisp->tt_isdst;
|
||||
j = sp->types[i];
|
||||
sp->types[i] = sp->ttis[j].tt_isdst;
|
||||
if (sp->ttis[j].tt_ttisgmt) {
|
||||
/* No adjustment to transition time */
|
||||
} else {
|
||||
/*
|
||||
** If summer time is in effect, and the
|
||||
** transition time was not specified as
|
||||
** standard time, add the summer time
|
||||
** offset to the transition time;
|
||||
** otherwise, add the standard time
|
||||
** offset to the transition time.
|
||||
*/
|
||||
/*
|
||||
** Transitions from DST to DDST
|
||||
** will effectively disappear since
|
||||
** POSIX provides for only one DST
|
||||
** offset.
|
||||
*/
|
||||
if (isdst && !sp->ttis[j].tt_ttisstd) {
|
||||
sp->ats[i] += dstoffset -
|
||||
theirdstoffset;
|
||||
} else {
|
||||
sp->ats[i] += stdoffset -
|
||||
theirstdoffset;
|
||||
}
|
||||
}
|
||||
theiroffset = -sp->ttis[j].tt_gmtoff;
|
||||
if (sp->ttis[j].tt_isdst)
|
||||
theirdstoffset = theiroffset;
|
||||
else theirstdoffset = theiroffset;
|
||||
}
|
||||
/*
|
||||
** Finally, fill in ttis.
|
||||
** ttisstd and ttisgmt need not be handled.
|
||||
*/
|
||||
sp->ttis[0].tt_gmtoff = -stdoffset;
|
||||
sp->ttis[0].tt_isdst = FALSE;
|
||||
sp->ttis[0].tt_abbrind = 0;
|
||||
sp->ttis[1].tt_gmtoff = -dstoffset;
|
||||
sp->ttis[1].tt_isdst = TRUE;
|
||||
sp->ttis[1].tt_abbrind = stdlen + 1;
|
||||
}
|
||||
} else {
|
||||
dstlen = 0;
|
||||
|
|
@ -826,17 +901,24 @@ static void
|
|||
gmtload(sp)
|
||||
struct state * const sp;
|
||||
{
|
||||
if (tzload(GMT, sp) != 0)
|
||||
(void) tzparse(GMT, sp, TRUE);
|
||||
if (tzload(gmt, sp) != 0)
|
||||
(void) tzparse(gmt, sp, TRUE);
|
||||
}
|
||||
|
||||
#ifndef STD_INSPIRED
|
||||
/*
|
||||
** A non-static declaration of tzsetwall in a system header file
|
||||
** may cause a warning about this upcoming static declaration...
|
||||
*/
|
||||
static
|
||||
#endif /* !defined STD_INSPIRED */
|
||||
void
|
||||
tzsetwall()
|
||||
tzsetwall P((void))
|
||||
{
|
||||
lcl_is_set = TRUE;
|
||||
if (lcl_is_set < 0)
|
||||
return;
|
||||
lcl_is_set = -1;
|
||||
|
||||
#ifdef ALL_STATE
|
||||
if (lclptr == NULL) {
|
||||
lclptr = (struct state *) malloc(sizeof *lclptr);
|
||||
|
|
@ -852,7 +934,7 @@ tzsetwall()
|
|||
}
|
||||
|
||||
void
|
||||
tzset()
|
||||
tzset P((void))
|
||||
{
|
||||
register const char * name;
|
||||
|
||||
|
|
@ -861,7 +943,13 @@ tzset()
|
|||
tzsetwall();
|
||||
return;
|
||||
}
|
||||
lcl_is_set = TRUE;
|
||||
|
||||
if (lcl_is_set > 0 && strcmp(lcl_TZname, name) == 0)
|
||||
return;
|
||||
lcl_is_set = (strlen(name) < sizeof(lcl_TZname));
|
||||
if (lcl_is_set)
|
||||
(void) strcpy(lcl_TZname, name);
|
||||
|
||||
#ifdef ALL_STATE
|
||||
if (lclptr == NULL) {
|
||||
lclptr = (struct state *) malloc(sizeof *lclptr);
|
||||
|
|
@ -879,7 +967,7 @@ tzset()
|
|||
lclptr->timecnt = 0;
|
||||
lclptr->ttis[0].tt_gmtoff = 0;
|
||||
lclptr->ttis[0].tt_abbrind = 0;
|
||||
(void) strcpy(lclptr->chars, GMT);
|
||||
(void) strcpy(lclptr->chars, gmt);
|
||||
} else if (tzload(name, lclptr) != 0)
|
||||
if (name[0] == ':' || tzparse(name, lclptr, FALSE) != 0)
|
||||
(void) gmtload(lclptr);
|
||||
|
|
@ -902,13 +990,11 @@ const time_t * const timep;
|
|||
const long offset;
|
||||
struct tm * const tmp;
|
||||
{
|
||||
register const struct state * sp;
|
||||
register struct state * sp;
|
||||
register const struct ttinfo * ttisp;
|
||||
register int i;
|
||||
const time_t t = *timep;
|
||||
|
||||
if (!lcl_is_set)
|
||||
tzset();
|
||||
sp = lclptr;
|
||||
#ifdef ALL_STATE
|
||||
if (sp == NULL) {
|
||||
|
|
@ -938,7 +1024,7 @@ struct tm * const tmp;
|
|||
*/
|
||||
timesub(&t, ttisp->tt_gmtoff, sp, tmp);
|
||||
tmp->tm_isdst = ttisp->tt_isdst;
|
||||
tzname[tmp->tm_isdst] = (char *) &sp->chars[ttisp->tt_abbrind];
|
||||
tzname[tmp->tm_isdst] = &sp->chars[ttisp->tt_abbrind];
|
||||
#ifdef TM_ZONE
|
||||
tmp->TM_ZONE = &sp->chars[ttisp->tt_abbrind];
|
||||
#endif /* defined TM_ZONE */
|
||||
|
|
@ -948,8 +1034,7 @@ struct tm *
|
|||
localtime(timep)
|
||||
const time_t * const timep;
|
||||
{
|
||||
static struct tm tm;
|
||||
|
||||
tzset();
|
||||
localsub(timep, 0L, &tm);
|
||||
return &tm;
|
||||
}
|
||||
|
|
@ -980,11 +1065,11 @@ struct tm * const tmp;
|
|||
** but this is no time for a treasure hunt.
|
||||
*/
|
||||
if (offset != 0)
|
||||
tmp->TM_ZONE = WILDABBR;
|
||||
tmp->TM_ZONE = wildabbr;
|
||||
else {
|
||||
#ifdef ALL_STATE
|
||||
if (gmtptr == NULL)
|
||||
tmp->TM_ZONE = GMT;
|
||||
tmp->TM_ZONE = gmt;
|
||||
else tmp->TM_ZONE = gmtptr->chars;
|
||||
#endif /* defined ALL_STATE */
|
||||
#ifndef ALL_STATE
|
||||
|
|
@ -998,8 +1083,6 @@ struct tm *
|
|||
gmtime(timep)
|
||||
const time_t * const timep;
|
||||
{
|
||||
static struct tm tm;
|
||||
|
||||
gmtsub(timep, 0L, &tm);
|
||||
return &tm;
|
||||
}
|
||||
|
|
@ -1011,8 +1094,6 @@ offtime(timep, offset)
|
|||
const time_t * const timep;
|
||||
const long offset;
|
||||
{
|
||||
static struct tm tm;
|
||||
|
||||
gmtsub(timep, offset, &tm);
|
||||
return &tm;
|
||||
}
|
||||
|
|
@ -1074,7 +1155,7 @@ register struct tm * const tmp;
|
|||
days = -24855;
|
||||
rem = -11648;
|
||||
}
|
||||
#endif /* mc68k */
|
||||
#endif /* defined mc68k */
|
||||
rem += (offset - corr);
|
||||
while (rem < 0) {
|
||||
rem += SECSPERDAY;
|
||||
|
|
@ -1087,30 +1168,27 @@ register struct tm * const tmp;
|
|||
tmp->tm_hour = (int) (rem / SECSPERHOUR);
|
||||
rem = rem % SECSPERHOUR;
|
||||
tmp->tm_min = (int) (rem / SECSPERMIN);
|
||||
tmp->tm_sec = (int) (rem % SECSPERMIN);
|
||||
if (hit)
|
||||
/*
|
||||
** A positive leap second requires a special
|
||||
** representation. This uses "... ??:59:60" et seq.
|
||||
*/
|
||||
tmp->tm_sec += hit;
|
||||
/*
|
||||
** A positive leap second requires a special
|
||||
** representation. This uses "... ??:59:60" et seq.
|
||||
*/
|
||||
tmp->tm_sec = (int) (rem % SECSPERMIN) + hit;
|
||||
tmp->tm_wday = (int) ((EPOCH_WDAY + days) % DAYSPERWEEK);
|
||||
if (tmp->tm_wday < 0)
|
||||
tmp->tm_wday += DAYSPERWEEK;
|
||||
y = EPOCH_YEAR;
|
||||
if (days >= 0)
|
||||
for ( ; ; ) {
|
||||
yleap = isleap(y);
|
||||
if (days < (long) year_lengths[yleap])
|
||||
break;
|
||||
++y;
|
||||
days = days - (long) year_lengths[yleap];
|
||||
}
|
||||
else do {
|
||||
--y;
|
||||
yleap = isleap(y);
|
||||
days = days + (long) year_lengths[yleap];
|
||||
} while (days < 0);
|
||||
#define LEAPS_THRU_END_OF(y) ((y) / 4 - (y) / 100 + (y) / 400)
|
||||
while (days < 0 || days >= (long) year_lengths[yleap = isleap(y)]) {
|
||||
register int newy;
|
||||
|
||||
newy = y + days / DAYSPERNYEAR;
|
||||
if (days < 0)
|
||||
--newy;
|
||||
days -= (newy - y) * DAYSPERNYEAR +
|
||||
LEAPS_THRU_END_OF(newy - 1) -
|
||||
LEAPS_THRU_END_OF(y - 1);
|
||||
y = newy;
|
||||
}
|
||||
tmp->tm_year = y - TM_YEAR_BASE;
|
||||
tmp->tm_yday = (int) days;
|
||||
ip = mon_lengths[yleap];
|
||||
|
|
@ -1127,13 +1205,20 @@ char *
|
|||
ctime(timep)
|
||||
const time_t * const timep;
|
||||
{
|
||||
/*
|
||||
** Section 4.12.3.2 of X3.159-1989 requires that
|
||||
** The ctime funciton converts the calendar time pointed to by timer
|
||||
** to local time in the form of a string. It is equivalent to
|
||||
** asctime(localtime(timer))
|
||||
*/
|
||||
return asctime(localtime(timep));
|
||||
}
|
||||
|
||||
/*
|
||||
** Adapted from code provided by Robert Elz, who writes:
|
||||
** The "best" way to do mktime I think is based on an idea of Bob
|
||||
** Kridle's (so its said...) from a long time ago. (mtxinu!kridle now).
|
||||
** Kridle's (so its said...) from a long time ago.
|
||||
** [kridle@xinet.com as of 1996-01-16.]
|
||||
** It does a binary search of the time_t space. Since time_t's are
|
||||
** just 32 bits, its a max of 32 iterations (even at 64 bits it
|
||||
** would still be very reasonable).
|
||||
|
|
@ -1152,8 +1237,8 @@ increment_overflow(number, delta)
|
|||
int * number;
|
||||
int delta;
|
||||
{
|
||||
int number0;
|
||||
|
||||
int number0;
|
||||
|
||||
number0 = *number;
|
||||
*number += delta;
|
||||
return (*number < number0) != (delta < 0);
|
||||
|
|
@ -1193,7 +1278,7 @@ register const struct tm * const btmp;
|
|||
static time_t
|
||||
time2(tmp, funcp, offset, okayp)
|
||||
struct tm * const tmp;
|
||||
void (* const funcp)();
|
||||
void (* const funcp) P((const time_t*, long, struct tm*));
|
||||
const long offset;
|
||||
int * const okayp;
|
||||
{
|
||||
|
|
@ -1223,10 +1308,12 @@ int * const okayp;
|
|||
while (yourtm.tm_mday <= 0) {
|
||||
if (increment_overflow(&yourtm.tm_year, -1))
|
||||
return WRONG;
|
||||
yourtm.tm_mday += year_lengths[isleap(yourtm.tm_year)];
|
||||
i = yourtm.tm_year + (1 < yourtm.tm_mon);
|
||||
yourtm.tm_mday += year_lengths[isleap(i)];
|
||||
}
|
||||
while (yourtm.tm_mday > DAYSPERLYEAR) {
|
||||
yourtm.tm_mday -= year_lengths[isleap(yourtm.tm_year)];
|
||||
i = yourtm.tm_year + (1 < yourtm.tm_mon);
|
||||
yourtm.tm_mday -= year_lengths[isleap(i)];
|
||||
if (increment_overflow(&yourtm.tm_year, 1))
|
||||
return WRONG;
|
||||
}
|
||||
|
|
@ -1261,17 +1348,16 @@ int * const okayp;
|
|||
yourtm.tm_sec = 0;
|
||||
}
|
||||
/*
|
||||
** Calculate the number of magnitude bits in a time_t
|
||||
** (this works regardless of whether time_t is
|
||||
** signed or unsigned, though lint complains if unsigned).
|
||||
** Divide the search space in half
|
||||
** (this works whether time_t is signed or unsigned).
|
||||
*/
|
||||
for (bits = 0, t = 1; t > 0; ++bits, t <<= 1)
|
||||
continue;
|
||||
bits = TYPE_BIT(time_t) - 1;
|
||||
/*
|
||||
** If time_t is signed, then 0 is the median value,
|
||||
** if time_t is unsigned, then 1 << bits is median.
|
||||
** If time_t is signed, then 0 is just above the median,
|
||||
** assuming two's complement arithmetic.
|
||||
** If time_t is unsigned, then (1 << bits) is just above the median.
|
||||
*/
|
||||
t = (t < 0) ? 0 : ((time_t) 1 << bits);
|
||||
t = TYPE_SIGNED(time_t) ? 0 : (((time_t) 1) << bits);
|
||||
for ( ; ; ) {
|
||||
(*funcp)(&t, offset, &mytm);
|
||||
dir = tmcomp(&mytm, &yourtm);
|
||||
|
|
@ -1279,10 +1365,10 @@ int * const okayp;
|
|||
if (bits-- < 0)
|
||||
return WRONG;
|
||||
if (bits < 0)
|
||||
--t;
|
||||
--t; /* may be needed if new t is minimal */
|
||||
else if (dir > 0)
|
||||
t -= (time_t) 1 << bits;
|
||||
else t += (time_t) 1 << bits;
|
||||
t -= ((time_t) 1) << bits;
|
||||
else t += ((time_t) 1) << bits;
|
||||
continue;
|
||||
}
|
||||
if (yourtm.tm_isdst < 0 || mytm.tm_isdst == yourtm.tm_isdst)
|
||||
|
|
@ -1303,10 +1389,10 @@ int * const okayp;
|
|||
if (sp == NULL)
|
||||
return WRONG;
|
||||
#endif /* defined ALL_STATE */
|
||||
for (i = 0; i < sp->typecnt; ++i) {
|
||||
for (i = sp->typecnt - 1; i >= 0; --i) {
|
||||
if (sp->ttis[i].tt_isdst != yourtm.tm_isdst)
|
||||
continue;
|
||||
for (j = 0; j < sp->typecnt; ++j) {
|
||||
for (j = sp->typecnt - 1; j >= 0; --j) {
|
||||
if (sp->ttis[j].tt_isdst == yourtm.tm_isdst)
|
||||
continue;
|
||||
newt = t + sp->ttis[j].tt_gmtoff -
|
||||
|
|
@ -1338,7 +1424,7 @@ label:
|
|||
static time_t
|
||||
time1(tmp, funcp, offset)
|
||||
struct tm * const tmp;
|
||||
void (* const funcp)();
|
||||
void (* const funcp) P((const time_t *, long, struct tm *));
|
||||
const long offset;
|
||||
{
|
||||
register time_t t;
|
||||
|
|
@ -1377,10 +1463,10 @@ const long offset;
|
|||
if (sp == NULL)
|
||||
return WRONG;
|
||||
#endif /* defined ALL_STATE */
|
||||
for (samei = 0; samei < sp->typecnt; ++samei) {
|
||||
for (samei = sp->typecnt - 1; samei >= 0; --samei) {
|
||||
if (sp->ttis[samei].tt_isdst != tmp->tm_isdst)
|
||||
continue;
|
||||
for (otheri = 0; otheri < sp->typecnt; ++otheri) {
|
||||
for (otheri = sp->typecnt - 1; otheri >= 0; --otheri) {
|
||||
if (sp->ttis[otheri].tt_isdst == tmp->tm_isdst)
|
||||
continue;
|
||||
tmp->tm_sec += sp->ttis[otheri].tt_gmtoff -
|
||||
|
|
@ -1401,6 +1487,7 @@ time_t
|
|||
mktime(tmp)
|
||||
struct tm * const tmp;
|
||||
{
|
||||
tzset();
|
||||
return time1(tmp, localsub, 0L);
|
||||
}
|
||||
|
||||
|
|
@ -1475,8 +1562,6 @@ time_t * timep;
|
|||
register struct lsinfo * lp;
|
||||
register int i;
|
||||
|
||||
if (!lcl_is_set)
|
||||
(void) tzset();
|
||||
sp = lclptr;
|
||||
i = sp->leapcnt;
|
||||
while (--i >= 0) {
|
||||
|
|
@ -1491,6 +1576,7 @@ time_t
|
|||
time2posix(t)
|
||||
time_t t;
|
||||
{
|
||||
tzset();
|
||||
return t - leapcorr(&t);
|
||||
}
|
||||
|
||||
|
|
@ -1501,6 +1587,7 @@ time_t t;
|
|||
time_t x;
|
||||
time_t y;
|
||||
|
||||
tzset();
|
||||
/*
|
||||
** For a positive leap second hit, the result
|
||||
** is not unique. For a negative leap second
|
||||
|
|
|
|||
|
|
@ -2,6 +2,11 @@
|
|||
|
||||
#define PRIVATE_H
|
||||
|
||||
/*
|
||||
** This file is in the public domain, so clarified as of
|
||||
** June 5, 1996 by Arthur David Olson (arthur_david_olson@nih.gov).
|
||||
*/
|
||||
|
||||
/*
|
||||
** This header is for use ONLY with the time conversion code.
|
||||
** There is no guarantee that it will remain unchanged,
|
||||
|
|
@ -16,12 +21,81 @@
|
|||
|
||||
#ifndef lint
|
||||
#ifndef NOID
|
||||
static char privatehid[] = "@(#)private.h 7.5";
|
||||
static char privatehid[] = "@(#)private.h 7.43";
|
||||
#endif /* !defined NOID */
|
||||
#endif /* !defined lint */
|
||||
|
||||
/*
|
||||
** const
|
||||
** Defaults for preprocessor symbols.
|
||||
** You can override these in your C compiler options, e.g. `-DHAVE_ADJTIME=0'.
|
||||
*/
|
||||
|
||||
#ifndef HAVE_ADJTIME
|
||||
#define HAVE_ADJTIME 1
|
||||
#endif /* !defined HAVE_ADJTIME */
|
||||
|
||||
#ifndef HAVE_GETTEXT
|
||||
#define HAVE_GETTEXT 0
|
||||
#endif /* !defined HAVE_GETTEXT */
|
||||
|
||||
#ifndef HAVE_SETTIMEOFDAY
|
||||
#define HAVE_SETTIMEOFDAY 3
|
||||
#endif /* !defined HAVE_SETTIMEOFDAY */
|
||||
|
||||
#ifndef HAVE_STRERROR
|
||||
#define HAVE_STRERROR 0
|
||||
#endif /* !defined HAVE_STRERROR */
|
||||
|
||||
#ifndef HAVE_UNISTD_H
|
||||
#define HAVE_UNISTD_H 1
|
||||
#endif /* !defined HAVE_UNISTD_H */
|
||||
|
||||
#ifndef HAVE_UTMPX_H
|
||||
#define HAVE_UTMPX_H 0
|
||||
#endif /* !defined HAVE_UTMPX_H */
|
||||
|
||||
#ifndef LOCALE_HOME
|
||||
#define LOCALE_HOME "/usr/lib/locale"
|
||||
#endif /* !defined LOCALE_HOME */
|
||||
|
||||
/*
|
||||
** Nested includes
|
||||
*/
|
||||
|
||||
#include "sys/types.h" /* for time_t */
|
||||
#include "stdio.h"
|
||||
#include "errno.h"
|
||||
#include "string.h"
|
||||
#include "limits.h" /* for CHAR_BIT */
|
||||
#include "time.h"
|
||||
#include "stdlib.h"
|
||||
|
||||
#if HAVE_GETTEXT - 0
|
||||
#include "libintl.h"
|
||||
#endif /* HAVE_GETTEXT - 0 */
|
||||
|
||||
#if HAVE_UNISTD_H - 0
|
||||
#include "unistd.h" /* for F_OK and R_OK */
|
||||
#endif /* HAVE_UNISTD_H - 0 */
|
||||
|
||||
#if !(HAVE_UNISTD_H - 0)
|
||||
#ifndef F_OK
|
||||
#define F_OK 0
|
||||
#endif /* !defined F_OK */
|
||||
#ifndef R_OK
|
||||
#define R_OK 4
|
||||
#endif /* !defined R_OK */
|
||||
#endif /* !(HAVE_UNISTD_H - 0) */
|
||||
|
||||
/* Unlike <ctype.h>'s isdigit, this also works if c < 0 | c > UCHAR_MAX. */
|
||||
#define is_digit(c) ((unsigned)(c) - '0' <= 9)
|
||||
|
||||
/*
|
||||
** Workarounds for compilers/systems.
|
||||
*/
|
||||
|
||||
/*
|
||||
** SunOS 4.1.1 cc lacks const.
|
||||
*/
|
||||
|
||||
#ifndef const
|
||||
|
|
@ -31,21 +105,7 @@ static char privatehid[] = "@(#)private.h 7.5";
|
|||
#endif /* !defined const */
|
||||
|
||||
/*
|
||||
** void
|
||||
*/
|
||||
|
||||
#ifndef void
|
||||
#ifndef __STDC__
|
||||
#ifndef vax
|
||||
#ifndef sun
|
||||
#define void char
|
||||
#endif /* !defined sun */
|
||||
#endif /* !defined vax */
|
||||
#endif /* !defined __STDC__ */
|
||||
#endif /* !defined void */
|
||||
|
||||
/*
|
||||
** P((args))
|
||||
** SunOS 4.1.1 cc lacks prototypes.
|
||||
*/
|
||||
|
||||
#ifndef P
|
||||
|
|
@ -53,36 +113,29 @@ static char privatehid[] = "@(#)private.h 7.5";
|
|||
#define P(x) x
|
||||
#endif /* defined __STDC__ */
|
||||
#ifndef __STDC__
|
||||
#define ASTERISK *
|
||||
#define P(x) ( /ASTERISK x ASTERISK/ )
|
||||
#define P(x) ()
|
||||
#endif /* !defined __STDC__ */
|
||||
#endif /* !defined P */
|
||||
|
||||
/*
|
||||
** genericptr_t
|
||||
** SunOS 4.1.1 headers lack EXIT_SUCCESS.
|
||||
*/
|
||||
|
||||
#ifdef __STDC__
|
||||
typedef void * genericptr_t;
|
||||
#endif /* defined __STDC__ */
|
||||
#ifndef __STDC__
|
||||
typedef char * genericptr_t;
|
||||
#endif /* !defined __STDC__ */
|
||||
#ifndef EXIT_SUCCESS
|
||||
#define EXIT_SUCCESS 0
|
||||
#endif /* !defined EXIT_SUCCESS */
|
||||
|
||||
#include "sys/types.h" /* for time_t */
|
||||
#include "stdio.h"
|
||||
#include "ctype.h"
|
||||
#include "errno.h"
|
||||
#include "string.h"
|
||||
#include "limits.h" /* for CHAR_BIT */
|
||||
#ifndef _TIME_
|
||||
#include "time.h"
|
||||
#endif /* !defined _TIME_ */
|
||||
/*
|
||||
** SunOS 4.1.1 headers lack EXIT_FAILURE.
|
||||
*/
|
||||
|
||||
#ifndef remove
|
||||
extern int unlink P((const char * filename));
|
||||
#define remove unlink
|
||||
#endif /* !defined remove */
|
||||
#ifndef EXIT_FAILURE
|
||||
#define EXIT_FAILURE 1
|
||||
#endif /* !defined EXIT_FAILURE */
|
||||
|
||||
/*
|
||||
** SunOS 4.1.1 headers lack FILENAME_MAX.
|
||||
*/
|
||||
|
||||
#ifndef FILENAME_MAX
|
||||
|
||||
|
|
@ -101,62 +154,27 @@ extern int unlink P((const char * filename));
|
|||
|
||||
#endif /* !defined FILENAME_MAX */
|
||||
|
||||
#ifndef EXIT_SUCCESS
|
||||
#define EXIT_SUCCESS 0
|
||||
#endif /* !defined EXIT_SUCCESS */
|
||||
|
||||
#ifndef EXIT_FAILURE
|
||||
#define EXIT_FAILURE 1
|
||||
#endif /* !defined EXIT_FAILURE */
|
||||
|
||||
#ifdef __STDC__
|
||||
|
||||
#define alloc_size_t size_t
|
||||
#define qsort_size_t size_t
|
||||
#define fwrite_size_t size_t
|
||||
|
||||
#endif /* defined __STDC__ */
|
||||
#ifndef __STDC__
|
||||
|
||||
#ifndef alloc_size_t
|
||||
#define alloc_size_t unsigned
|
||||
#endif /* !defined alloc_size_t */
|
||||
|
||||
#ifndef qsort_size_t
|
||||
#ifdef USG
|
||||
#define qsort_size_t unsigned
|
||||
#endif /* defined USG */
|
||||
#ifndef USG
|
||||
#define qsort_size_t int
|
||||
#endif /* !defined USG */
|
||||
#endif /* !defined qsort_size_t */
|
||||
|
||||
#ifndef fwrite_size_t
|
||||
#define fwrite_size_t int
|
||||
#endif /* !defined fwrite_size_t */
|
||||
|
||||
#ifndef USG
|
||||
extern char * sprintf P((char * buf, const char * format, ...));
|
||||
#endif /* !defined USG */
|
||||
|
||||
#endif /* !defined __STDC__ */
|
||||
|
||||
/*
|
||||
** Ensure that these are declared--redundantly declaring them shouldn't hurt.
|
||||
** SunOS 4.1.1 libraries lack remove.
|
||||
*/
|
||||
|
||||
extern char * getenv P((const char * name));
|
||||
extern genericptr_t malloc P((alloc_size_t size));
|
||||
extern genericptr_t calloc P((alloc_size_t nelem, alloc_size_t elsize));
|
||||
extern genericptr_t realloc P((genericptr_t oldptr, alloc_size_t newsize));
|
||||
#ifndef remove
|
||||
extern int unlink P((const char * filename));
|
||||
#define remove unlink
|
||||
#endif /* !defined remove */
|
||||
|
||||
#ifdef USG
|
||||
extern void exit P((int s));
|
||||
extern void qsort P((genericptr_t base, qsort_size_t nelem,
|
||||
qsort_size_t elsize, int (*comp)()));
|
||||
extern void perror P((const char * string));
|
||||
extern void free P((char * buf));
|
||||
#endif /* defined USG */
|
||||
/*
|
||||
** Some ancient errno.h implementations don't declare errno.
|
||||
** But some newer errno.h implementations define it as a macro.
|
||||
** Fix the former without affecting the latter.
|
||||
*/
|
||||
#ifndef errno
|
||||
extern int errno;
|
||||
#endif /* !defined errno */
|
||||
|
||||
/*
|
||||
** Finally, some convenience items.
|
||||
*/
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
|
|
@ -166,20 +184,69 @@ extern void free P((char * buf));
|
|||
#define FALSE 0
|
||||
#endif /* !defined FALSE */
|
||||
|
||||
#ifndef TYPE_BIT
|
||||
#define TYPE_BIT(type) (sizeof (type) * CHAR_BIT)
|
||||
#endif /* !defined TYPE_BIT */
|
||||
|
||||
#ifndef TYPE_SIGNED
|
||||
#define TYPE_SIGNED(type) (((type) -1) < 0)
|
||||
#endif /* !defined TYPE_SIGNED */
|
||||
|
||||
#ifndef INT_STRLEN_MAXIMUM
|
||||
/*
|
||||
** 302 / 1000 is log10(2.0) rounded up.
|
||||
** Subtract one for the sign bit;
|
||||
** Subtract one for the sign bit if the type is signed;
|
||||
** add one for integer division truncation;
|
||||
** add one more for a minus sign.
|
||||
** add one more for a minus sign if the type is signed.
|
||||
*/
|
||||
#define INT_STRLEN_MAXIMUM(type) \
|
||||
((sizeof(type) * CHAR_BIT - 1) * 302 / 1000 + 2)
|
||||
((TYPE_BIT(type) - TYPE_SIGNED(type)) * 302 / 100 + 1 + TYPE_SIGNED(type))
|
||||
#endif /* !defined INT_STRLEN_MAXIMUM */
|
||||
|
||||
/*
|
||||
** UNIX is a registered trademark of AT&T.
|
||||
** VAX is a trademark of Digital Equipment Corporation.
|
||||
** INITIALIZE(x)
|
||||
*/
|
||||
|
||||
#ifndef GNUC_or_lint
|
||||
#ifdef lint
|
||||
#define GNUC_or_lint
|
||||
#endif /* defined lint */
|
||||
#ifndef lint
|
||||
#ifdef __GNUC__
|
||||
#define GNUC_or_lint
|
||||
#endif /* defined __GNUC__ */
|
||||
#endif /* !defined lint */
|
||||
#endif /* !defined GNUC_or_lint */
|
||||
|
||||
#ifndef INITIALIZE
|
||||
#ifdef GNUC_or_lint
|
||||
#define INITIALIZE(x) ((x) = 0)
|
||||
#endif /* defined GNUC_or_lint */
|
||||
#ifndef GNUC_or_lint
|
||||
#define INITIALIZE(x)
|
||||
#endif /* !defined GNUC_or_lint */
|
||||
#endif /* !defined INITIALIZE */
|
||||
|
||||
/*
|
||||
** For the benefit of GNU folk...
|
||||
** `_(MSGID)' uses the current locale's message library string for MSGID.
|
||||
** The default is to use gettext if available, and use MSGID otherwise.
|
||||
*/
|
||||
|
||||
#ifndef _
|
||||
#if HAVE_GETTEXT - 0
|
||||
#define _(msgid) gettext(msgid)
|
||||
#else /* !(HAVE_GETTEXT - 0) */
|
||||
#define _(msgid) msgid
|
||||
#endif /* !(HAVE_GETTEXT - 0) */
|
||||
#endif /* !defined _ */
|
||||
|
||||
#ifndef TZ_DOMAIN
|
||||
#define TZ_DOMAIN "tz"
|
||||
#endif /* !defined TZ_DOMAIN */
|
||||
|
||||
/*
|
||||
** UNIX was a registered trademark of UNIX System Laboratories in 1993.
|
||||
*/
|
||||
|
||||
#endif /* !defined PRIVATE_H */
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
#ifndef lint
|
||||
#ifndef NOID
|
||||
static char elsieid[] = "@(#)strftime.c 7.19";
|
||||
static char elsieid[] = "@(#)strftime.c 7.47";
|
||||
/*
|
||||
** Based on the UCB version with the ID appearing below.
|
||||
** This is ANSIish only when time is treated identically in all locales and
|
||||
** when "multibyte character == plain character".
|
||||
** This is ANSIish only when "multibyte character == plain character".
|
||||
*/
|
||||
#endif /* !defined NOID */
|
||||
#endif /* !defined lint */
|
||||
|
|
@ -12,64 +11,122 @@ static char elsieid[] = "@(#)strftime.c 7.19";
|
|||
#include "private.h"
|
||||
|
||||
/*
|
||||
* Copyright (c) 1989 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms are permitted
|
||||
* provided that the above copyright notice and this paragraph are
|
||||
* duplicated in all such forms and that any documentation,
|
||||
* advertising materials, and other materials related to such
|
||||
* distribution and use acknowledge that the software was developed
|
||||
* by the University of California, Berkeley. The name of the
|
||||
* University may not be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
** Copyright (c) 1989 The Regents of the University of California.
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms are permitted
|
||||
** provided that the above copyright notice and this paragraph are
|
||||
** duplicated in all such forms and that any documentation,
|
||||
** advertising materials, and other materials related to such
|
||||
** distribution and use acknowledge that the software was developed
|
||||
** by the University of California, Berkeley. The name of the
|
||||
** University may not be used to endorse or promote products derived
|
||||
** from this software without specific prior written permission.
|
||||
** THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
|
||||
** IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||
** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
#ifndef LIBC_SCCS
|
||||
#ifndef lint
|
||||
static const char sccsid[] = "@(#)strftime.c 5.4 (Berkeley) 3/14/89";
|
||||
static const char sccsid[] = "@(#)strftime.c 5.4 (Berkeley) 3/14/89";
|
||||
#endif /* !defined lint */
|
||||
#endif /* !defined LIBC_SCCS */
|
||||
|
||||
#include "tzfile.h"
|
||||
#include "fcntl.h"
|
||||
#include "locale.h"
|
||||
|
||||
static const char afmt[][4] = {
|
||||
"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
|
||||
};
|
||||
static const char Afmt[][10] = {
|
||||
"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday",
|
||||
"Saturday"
|
||||
};
|
||||
static const char bfmt[][4] = {
|
||||
"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep",
|
||||
"Oct", "Nov", "Dec"
|
||||
};
|
||||
static const char Bfmt[][10] = {
|
||||
"January", "February", "March", "April", "May", "June", "July",
|
||||
"August", "September", "October", "November", "December"
|
||||
struct lc_time_T {
|
||||
const char * mon[12];
|
||||
const char * month[12];
|
||||
const char * wday[7];
|
||||
const char * weekday[7];
|
||||
const char * X_fmt;
|
||||
const char * x_fmt;
|
||||
const char * c_fmt;
|
||||
const char * am;
|
||||
const char * pm;
|
||||
const char * date_fmt;
|
||||
};
|
||||
|
||||
static char *_add P((const char *, char *, const char *));
|
||||
static char *_conv P((int, const char *, char *, const char *));
|
||||
static char *_fmt P((const char *, const struct tm *, char *, const char *));
|
||||
#ifdef LOCALE_HOME
|
||||
#include "sys/stat.h"
|
||||
static struct lc_time_T localebuf;
|
||||
static struct lc_time_T * _loc P((void));
|
||||
#define Locale _loc()
|
||||
#endif /* defined LOCALE_HOME */
|
||||
#ifndef LOCALE_HOME
|
||||
#define Locale (&C_time_locale)
|
||||
#endif /* !defined LOCALE_HOME */
|
||||
|
||||
static const struct lc_time_T C_time_locale = {
|
||||
{
|
||||
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
|
||||
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
|
||||
}, {
|
||||
"January", "February", "March", "April", "May", "June",
|
||||
"July", "August", "September", "October", "November", "December"
|
||||
}, {
|
||||
"Sun", "Mon", "Tue", "Wed",
|
||||
"Thu", "Fri", "Sat"
|
||||
}, {
|
||||
"Sunday", "Monday", "Tuesday", "Wednesday",
|
||||
"Thursday", "Friday", "Saturday"
|
||||
},
|
||||
|
||||
/* X_fmt */
|
||||
"%H:%M:%S",
|
||||
|
||||
/*
|
||||
** x_fmt
|
||||
** Since the C language standard calls for
|
||||
** "date, using locale's date format," anything goes.
|
||||
** Using just numbers (as here) makes Quakers happier;
|
||||
** it's also compatible with SVR4.
|
||||
*/
|
||||
"%m/%d/%y",
|
||||
|
||||
/*
|
||||
** c_fmt
|
||||
** Note that
|
||||
** "%a %b %d %H:%M:%S %Y"
|
||||
** is used by Solaris 2.3.
|
||||
*/
|
||||
"%D %X", /* %m/%d/%y %H:%M:%S */
|
||||
|
||||
/* am */
|
||||
"AM",
|
||||
|
||||
/* pm */
|
||||
"PM",
|
||||
|
||||
/* date_fmt */
|
||||
"%a %b %e %H:%M:%S %Z %Y"
|
||||
};
|
||||
|
||||
static char * _add P((const char *, char *, const char *));
|
||||
static char * _conv P((int, const char *, char *, const char *));
|
||||
static char * _fmt P((const char *, const struct tm *, char *, const char *));
|
||||
|
||||
size_t strftime P((char *, size_t, const char *, const struct tm *));
|
||||
|
||||
extern char *tzname[];
|
||||
extern char * tzname[];
|
||||
|
||||
size_t
|
||||
strftime(s, maxsize, format, t)
|
||||
char *s;
|
||||
size_t maxsize;
|
||||
const char *format;
|
||||
const struct tm *t;
|
||||
char * const s;
|
||||
const size_t maxsize;
|
||||
const char * const format;
|
||||
const struct tm * const t;
|
||||
{
|
||||
char *p;
|
||||
char * p;
|
||||
|
||||
p = _fmt(format, t, s, s + maxsize);
|
||||
tzset();
|
||||
#ifdef LOCALE_HOME
|
||||
localebuf.mon[0] = 0;
|
||||
#endif /* defined LOCALE_HOME */
|
||||
p = _fmt(((format == NULL) ? "%c" : format), t, s, s + maxsize);
|
||||
if (p == s + maxsize)
|
||||
return 0;
|
||||
*p = '\0';
|
||||
|
|
@ -78,37 +135,38 @@ strftime(s, maxsize, format, t)
|
|||
|
||||
static char *
|
||||
_fmt(format, t, pt, ptlim)
|
||||
const char *format;
|
||||
const struct tm *t;
|
||||
char *pt;
|
||||
const char *ptlim;
|
||||
const char * format;
|
||||
const struct tm * const t;
|
||||
char * pt;
|
||||
const char * const ptlim;
|
||||
{
|
||||
for (; *format; ++format) {
|
||||
for ( ; *format; ++format) {
|
||||
if (*format == '%') {
|
||||
label:
|
||||
switch(*++format) {
|
||||
switch (*++format) {
|
||||
case '\0':
|
||||
--format;
|
||||
break;
|
||||
case 'A':
|
||||
pt = _add((t->tm_wday < 0 || t->tm_wday > 6) ?
|
||||
"?" : Afmt[t->tm_wday], pt, ptlim);
|
||||
"?" : Locale->weekday[t->tm_wday],
|
||||
pt, ptlim);
|
||||
continue;
|
||||
case 'a':
|
||||
pt = _add((t->tm_wday < 0 || t->tm_wday > 6) ?
|
||||
"?" : afmt[t->tm_wday], pt, ptlim);
|
||||
"?" : Locale->wday[t->tm_wday],
|
||||
pt, ptlim);
|
||||
continue;
|
||||
case 'B':
|
||||
pt = _add((t->tm_mon < 0 || t->tm_mon > 11) ?
|
||||
"?" : Bfmt[t->tm_mon], pt, ptlim);
|
||||
"?" : Locale->month[t->tm_mon],
|
||||
pt, ptlim);
|
||||
continue;
|
||||
case 'b':
|
||||
case 'h':
|
||||
pt = _add((t->tm_mon < 0 || t->tm_mon > 11) ?
|
||||
"?" : bfmt[t->tm_mon], pt, ptlim);
|
||||
continue;
|
||||
case 'c':
|
||||
pt = _fmt("%D %X", t, pt, ptlim);
|
||||
"?" : Locale->mon[t->tm_mon],
|
||||
pt, ptlim);
|
||||
continue;
|
||||
case 'C':
|
||||
/*
|
||||
|
|
@ -121,27 +179,10 @@ label:
|
|||
pt = _conv((t->tm_year + TM_YEAR_BASE) / 100,
|
||||
"%02d", pt, ptlim);
|
||||
continue;
|
||||
case 'D':
|
||||
pt = _fmt("%m/%d/%y", t, pt, ptlim);
|
||||
case 'c':
|
||||
pt = _fmt(Locale->c_fmt, t, pt, ptlim);
|
||||
continue;
|
||||
case 'x':
|
||||
/*
|
||||
** Version 3.0 of strftime from Arnold Robbins
|
||||
** (arnold@skeeve.atl.ga.us) does the
|
||||
** equivalent of...
|
||||
** _fmt("%a %b %e %Y");
|
||||
** ...for %x; since the X3J11 C language
|
||||
** standard calls for "date, using locale's
|
||||
** date format," anything goes. Using just
|
||||
** numbers (as here) makes Quakers happier.
|
||||
** Word from Paul Eggert (eggert@twinsun.com)
|
||||
** is that %Y-%m-%d is the ISO standard date
|
||||
** format, specified in ISO 2014 and later
|
||||
** ISO 8601:1988, with a summary available in
|
||||
** pub/doc/ISO/english/ISO8601.ps.Z on
|
||||
** ftp.uni-erlangen.de.
|
||||
** (ado, 5/30/93)
|
||||
*/
|
||||
case 'D':
|
||||
pt = _fmt("%m/%d/%y", t, pt, ptlim);
|
||||
continue;
|
||||
case 'd':
|
||||
|
|
@ -220,7 +261,9 @@ label:
|
|||
pt = _add("\n", pt, ptlim);
|
||||
continue;
|
||||
case 'p':
|
||||
pt = _add(t->tm_hour >= 12 ? "PM" : "AM",
|
||||
pt = _add((t->tm_hour >= 12) ?
|
||||
Locale->pm :
|
||||
Locale->am,
|
||||
pt, ptlim);
|
||||
continue;
|
||||
case 'R':
|
||||
|
|
@ -232,8 +275,24 @@ label:
|
|||
case 'S':
|
||||
pt = _conv(t->tm_sec, "%02d", pt, ptlim);
|
||||
continue;
|
||||
case 's':
|
||||
{
|
||||
struct tm tm;
|
||||
char buf[INT_STRLEN_MAXIMUM(
|
||||
time_t) + 1];
|
||||
time_t mkt;
|
||||
|
||||
tm = *t;
|
||||
mkt = mktime(&tm);
|
||||
if (TYPE_SIGNED(time_t))
|
||||
(void) sprintf(buf, "%ld",
|
||||
(long) mkt);
|
||||
else (void) sprintf(buf, "%lu",
|
||||
(unsigned long) mkt);
|
||||
pt = _add(buf, pt, ptlim);
|
||||
}
|
||||
continue;
|
||||
case 'T':
|
||||
case 'X':
|
||||
pt = _fmt("%H:%M:%S", t, pt, ptlim);
|
||||
continue;
|
||||
case 't':
|
||||
|
|
@ -253,66 +312,86 @@ label:
|
|||
pt = _conv((t->tm_wday == 0) ? 7 : t->tm_wday,
|
||||
"%d", pt, ptlim);
|
||||
continue;
|
||||
case 'V':
|
||||
/*
|
||||
** From Arnold Robbins' strftime version 3.0:
|
||||
** "the week number of the year (the first
|
||||
** Monday as the first day of week 1) as a
|
||||
** decimal number (01-53). The method for
|
||||
** determining the week number is as specified
|
||||
** by ISO 8601 (to wit: if the week containing
|
||||
** January 1 has four or more days in the new
|
||||
** year, then it is week 1, otherwise it is
|
||||
** week 53 of the previous year and the next
|
||||
** week is week 1)."
|
||||
** (ado, 5/24/93)
|
||||
*/
|
||||
/*
|
||||
** XXX--If January 1 falls on a Friday,
|
||||
** January 1-3 are part of week 53 of the
|
||||
** previous year. By analogy, if January
|
||||
** 1 falls on a Thursday, are December 29-31
|
||||
** of the PREVIOUS year part of week 1???
|
||||
** (ado 5/24/93)
|
||||
**
|
||||
** You are understood not to expect this.
|
||||
*/
|
||||
case 'V': /* ISO 8601 week number */
|
||||
case 'G': /* ISO 8601 year (four digits) */
|
||||
case 'g': /* ISO 8601 year (two digits) */
|
||||
/*
|
||||
** From Arnold Robbins' strftime version 3.0: "the week number of the
|
||||
** year (the first Monday as the first day of week 1) as a decimal number
|
||||
** (01-53)."
|
||||
** (ado, 1993-05-24)
|
||||
**
|
||||
** From "http://www.ft.uni-erlangen.de/~mskuhn/iso-time.html" by Markus Kuhn:
|
||||
** "Week 01 of a year is per definition the first week which has the
|
||||
** Thursday in this year, which is equivalent to the week which contains
|
||||
** the fourth day of January. In other words, the first week of a new year
|
||||
** is the week which has the majority of its days in the new year. Week 01
|
||||
** might also contain days from the previous year and the week before week
|
||||
** 01 of a year is the last week (52 or 53) of the previous year even if
|
||||
** it contains days from the new year. A week starts with Monday (day 1)
|
||||
** and ends with Sunday (day 7). For example, the first week of the year
|
||||
** 1997 lasts from 1996-12-30 to 1997-01-05..."
|
||||
** (ado, 1996-01-02)
|
||||
*/
|
||||
{
|
||||
int i;
|
||||
int year;
|
||||
int yday;
|
||||
int wday;
|
||||
int w;
|
||||
|
||||
i = (t->tm_yday + 10 - (t->tm_wday ?
|
||||
(t->tm_wday - 1) : 6)) / 7;
|
||||
if (i == 0) {
|
||||
year = t->tm_year + TM_YEAR_BASE;
|
||||
yday = t->tm_yday;
|
||||
wday = t->tm_wday;
|
||||
for ( ; ; ) {
|
||||
int len;
|
||||
int bot;
|
||||
int top;
|
||||
|
||||
len = isleap(year) ?
|
||||
DAYSPERLYEAR :
|
||||
DAYSPERNYEAR;
|
||||
/*
|
||||
** What day of the week does
|
||||
** January 1 fall on?
|
||||
** What yday (-3 ... 3) does
|
||||
** the ISO year begin on?
|
||||
*/
|
||||
i = t->tm_wday -
|
||||
(t->tm_yday - 1);
|
||||
bot = ((yday + 11 - wday) %
|
||||
DAYSPERWEEK) - 3;
|
||||
/*
|
||||
** Fri Jan 1: 53
|
||||
** Sun Jan 1: 52
|
||||
** Sat Jan 1: 53 if previous
|
||||
** year a leap
|
||||
** year, else 52
|
||||
** What yday does the NEXT
|
||||
** ISO year begin on?
|
||||
*/
|
||||
if (i == TM_FRIDAY)
|
||||
i = 53;
|
||||
else if (i == TM_SUNDAY)
|
||||
i = 52;
|
||||
else i = isleap(t->tm_year +
|
||||
TM_YEAR_BASE) ?
|
||||
53 : 52;
|
||||
#ifdef XPG4_1994_04_09
|
||||
/*
|
||||
** As of 4/9/94, though,
|
||||
** XPG4 calls for 53
|
||||
** unconditionally.
|
||||
*/
|
||||
i = 53;
|
||||
#endif /* defined XPG4_1994_04_09 */
|
||||
top = bot -
|
||||
(len % DAYSPERWEEK);
|
||||
if (top < -3)
|
||||
top += DAYSPERWEEK;
|
||||
top += len;
|
||||
if (yday >= top) {
|
||||
++year;
|
||||
w = 1;
|
||||
break;
|
||||
}
|
||||
if (yday >= bot) {
|
||||
w = 1 + ((yday - bot) /
|
||||
DAYSPERWEEK);
|
||||
break;
|
||||
}
|
||||
--year;
|
||||
yday += isleap(year) ?
|
||||
DAYSPERLYEAR :
|
||||
DAYSPERNYEAR;
|
||||
}
|
||||
pt = _conv(i, "%02d", pt, ptlim);
|
||||
#ifdef XPG4_1994_04_09
|
||||
if (w == 52 && t->tm_mon == TM_JANUARY)
|
||||
w = 53;
|
||||
#endif /* defined XPG4_1994_04_09 */
|
||||
if (*format == 'V')
|
||||
pt = _conv(w, "%02d",
|
||||
pt, ptlim);
|
||||
else if (*format == 'G')
|
||||
pt = _conv(year, "%02d",
|
||||
pt, ptlim);
|
||||
else pt = _conv(year, "%04d",
|
||||
pt, ptlim);
|
||||
}
|
||||
continue;
|
||||
case 'v':
|
||||
|
|
@ -332,6 +411,12 @@ label:
|
|||
case 'w':
|
||||
pt = _conv(t->tm_wday, "%d", pt, ptlim);
|
||||
continue;
|
||||
case 'X':
|
||||
pt = _fmt(Locale->X_fmt, t, pt, ptlim);
|
||||
continue;
|
||||
case 'x':
|
||||
pt = _fmt(Locale->x_fmt, t, pt, ptlim);
|
||||
continue;
|
||||
case 'y':
|
||||
pt = _conv((t->tm_year + TM_YEAR_BASE) % 100,
|
||||
"%02d", pt, ptlim);
|
||||
|
|
@ -342,7 +427,7 @@ label:
|
|||
continue;
|
||||
case 'Z':
|
||||
#ifdef TM_ZONE
|
||||
if (t->TM_ZONE)
|
||||
if (t->TM_ZONE != NULL)
|
||||
pt = _add(t->TM_ZONE, pt, ptlim);
|
||||
else
|
||||
#endif /* defined TM_ZONE */
|
||||
|
|
@ -351,6 +436,9 @@ label:
|
|||
pt, ptlim);
|
||||
} else pt = _add("?", pt, ptlim);
|
||||
continue;
|
||||
case '+':
|
||||
pt = _fmt(Locale->date_fmt, t, pt, ptlim);
|
||||
continue;
|
||||
case '%':
|
||||
/*
|
||||
* X311J/88-090 (4.12.3.5): if conversion char is
|
||||
|
|
@ -370,12 +458,12 @@ label:
|
|||
|
||||
static char *
|
||||
_conv(n, format, pt, ptlim)
|
||||
int n;
|
||||
const char *format;
|
||||
char *pt;
|
||||
const char *ptlim;
|
||||
const int n;
|
||||
const char * const format;
|
||||
char * const pt;
|
||||
const char * const ptlim;
|
||||
{
|
||||
char buf[INT_STRLEN_MAXIMUM(int) + 1];
|
||||
char buf[INT_STRLEN_MAXIMUM(int) + 1];
|
||||
|
||||
(void) sprintf(buf, format, n);
|
||||
return _add(buf, pt, ptlim);
|
||||
|
|
@ -383,11 +471,134 @@ _conv(n, format, pt, ptlim)
|
|||
|
||||
static char *
|
||||
_add(str, pt, ptlim)
|
||||
const char *str;
|
||||
char *pt;
|
||||
const char *ptlim;
|
||||
const char * str;
|
||||
char * pt;
|
||||
const char * const ptlim;
|
||||
{
|
||||
while (pt < ptlim && (*pt = *str++) != '\0')
|
||||
++pt;
|
||||
return pt;
|
||||
}
|
||||
|
||||
#ifdef LOCALE_HOME
|
||||
static struct lc_time_T *
|
||||
_loc P((void))
|
||||
{
|
||||
static const char locale_home[] = LOCALE_HOME;
|
||||
static const char lc_time[] = "LC_TIME";
|
||||
static char * locale_buf;
|
||||
static char locale_buf_C[] = "C";
|
||||
|
||||
int fd;
|
||||
int oldsun; /* "...ain't got nothin' to do..." */
|
||||
char * lbuf;
|
||||
char * name;
|
||||
char * p;
|
||||
const char ** ap;
|
||||
const char * plim;
|
||||
char filename[FILENAME_MAX];
|
||||
struct stat st;
|
||||
size_t namesize;
|
||||
size_t bufsize;
|
||||
|
||||
/*
|
||||
** Use localebuf.mon[0] to signal whether locale is already set up.
|
||||
*/
|
||||
if (localebuf.mon[0])
|
||||
return &localebuf;
|
||||
name = setlocale(LC_TIME, (char *) NULL);
|
||||
if (name == NULL || *name == '\0')
|
||||
goto no_locale;
|
||||
/*
|
||||
** If the locale name is the same as our cache, use the cache.
|
||||
*/
|
||||
lbuf = locale_buf;
|
||||
if (lbuf != NULL && strcmp(name, lbuf) == 0) {
|
||||
p = lbuf;
|
||||
for (ap = (const char **) &localebuf;
|
||||
ap < (const char **) (&localebuf + 1);
|
||||
++ap)
|
||||
*ap = p += strlen(p) + 1;
|
||||
return &localebuf;
|
||||
}
|
||||
/*
|
||||
** Slurp the locale file into the cache.
|
||||
*/
|
||||
namesize = strlen(name) + 1;
|
||||
if (sizeof(filename) <
|
||||
sizeof(locale_home) + namesize + sizeof(lc_time))
|
||||
goto no_locale;
|
||||
oldsun = 0;
|
||||
(void) sprintf(filename, "%s/%s/%s", locale_home, name, lc_time);
|
||||
fd = open(filename, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
/*
|
||||
** Old Sun systems have a different naming and data convention.
|
||||
*/
|
||||
oldsun = 1;
|
||||
(void) sprintf(filename, "%s/%s/%s", locale_home,
|
||||
lc_time, name);
|
||||
fd = open(filename, O_RDONLY);
|
||||
if (fd < 0)
|
||||
goto no_locale;
|
||||
}
|
||||
if (fstat(fd, &st) != 0)
|
||||
goto bad_locale;
|
||||
if (st.st_size <= 0)
|
||||
goto bad_locale;
|
||||
bufsize = namesize + st.st_size;
|
||||
locale_buf = NULL;
|
||||
lbuf = (lbuf == NULL || lbuf == locale_buf_C) ?
|
||||
malloc(bufsize) : realloc(lbuf, bufsize);
|
||||
if (lbuf == NULL)
|
||||
goto bad_locale;
|
||||
(void) strcpy(lbuf, name);
|
||||
p = lbuf + namesize;
|
||||
plim = p + st.st_size;
|
||||
if (read(fd, p, (size_t) st.st_size) != st.st_size)
|
||||
goto bad_lbuf;
|
||||
if (close(fd) != 0)
|
||||
goto bad_lbuf;
|
||||
/*
|
||||
** Parse the locale file into localebuf.
|
||||
*/
|
||||
if (plim[-1] != '\n')
|
||||
goto bad_lbuf;
|
||||
for (ap = (const char **) &localebuf;
|
||||
ap < (const char **) (&localebuf + 1);
|
||||
++ap) {
|
||||
if (p == plim)
|
||||
goto bad_lbuf;
|
||||
*ap = p;
|
||||
while (*p != '\n')
|
||||
++p;
|
||||
*p++ = '\0';
|
||||
}
|
||||
if (oldsun) {
|
||||
/*
|
||||
** SunOS 4 used an obsolescent format; see localdtconv(3).
|
||||
** c_fmt had the ``short format for dates and times together''
|
||||
** (SunOS 4 date, "%a %b %e %T %Z %Y" in the C locale);
|
||||
** date_fmt had the ``long format for dates''
|
||||
** (SunOS 4 strftime %C, "%A, %B %e, %Y" in the C locale).
|
||||
** Discard the latter in favor of the former.
|
||||
*/
|
||||
localebuf.date_fmt = localebuf.c_fmt;
|
||||
}
|
||||
/*
|
||||
** Record the successful parse in the cache.
|
||||
*/
|
||||
locale_buf = lbuf;
|
||||
|
||||
return &localebuf;
|
||||
|
||||
bad_lbuf:
|
||||
free(lbuf);
|
||||
bad_locale:
|
||||
(void) close(fd);
|
||||
no_locale:
|
||||
localebuf = C_time_locale;
|
||||
locale_buf = locale_buf_C;
|
||||
return &localebuf;
|
||||
}
|
||||
#endif /* defined LOCALE_HOME */
|
||||
|
|
|
|||
|
|
@ -2,6 +2,11 @@
|
|||
|
||||
#define TZFILE_H
|
||||
|
||||
/*
|
||||
** This file is in the public domain, so clarified as of
|
||||
** June 5, 1996 by Arthur David Olson (arthur_david_olson@nih.gov).
|
||||
*/
|
||||
|
||||
/*
|
||||
** This header is for use ONLY with the time conversion code.
|
||||
** There is no guarantee that it will remain unchanged,
|
||||
|
|
@ -16,7 +21,7 @@
|
|||
|
||||
#ifndef lint
|
||||
#ifndef NOID
|
||||
static char tzfilehid[] = "@(#)tzfile.h 7.4";
|
||||
static char tzfilehid[] = "@(#)tzfile.h 7.8";
|
||||
#endif /* !defined NOID */
|
||||
#endif /* !defined lint */
|
||||
|
||||
|
|
@ -41,7 +46,8 @@ static char tzfilehid[] = "@(#)tzfile.h 7.4";
|
|||
*/
|
||||
|
||||
struct tzhead {
|
||||
char tzh_reserved[24]; /* reserved for future use */
|
||||
char tzh_reserved[20]; /* reserved for future use */
|
||||
char tzh_ttisgmtcnt[4]; /* coded number of trans. time flags */
|
||||
char tzh_ttisstdcnt[4]; /* coded number of trans. time flags */
|
||||
char tzh_leapcnt[4]; /* coded number of leap seconds */
|
||||
char tzh_timecnt[4]; /* coded number of transition times */
|
||||
|
|
@ -67,6 +73,11 @@ struct tzhead {
|
|||
** transition time is wall clock time
|
||||
** if absent, transition times are
|
||||
** assumed to be wall clock time
|
||||
** tzh_ttisgmtcnt (char)s indexed by type; if TRUE, transition
|
||||
** time is GMT, if FALSE,
|
||||
** transition time is local time
|
||||
** if absent, transition times are
|
||||
** assumed to be local time
|
||||
*/
|
||||
|
||||
/*
|
||||
|
|
@ -89,7 +100,11 @@ struct tzhead {
|
|||
#define TZ_MAX_TYPES 256 /* Limited by what (unsigned char)'s can hold */
|
||||
#endif /* !defined NOSOLAR */
|
||||
#ifdef NOSOLAR
|
||||
#define TZ_MAX_TYPES 10 /* Maximum number of local time types */
|
||||
/*
|
||||
** Must be at least 14 for Europe/Riga as of Jan 12 1995,
|
||||
** as noted by Earl Chew <earl@hpato.aus.hp.com>.
|
||||
*/
|
||||
#define TZ_MAX_TYPES 20 /* Maximum number of local time types */
|
||||
#endif /* !defined NOSOLAR */
|
||||
#endif /* !defined TZ_MAX_TYPES */
|
||||
|
||||
|
|
@ -143,7 +158,7 @@ struct tzhead {
|
|||
** that will probably do.
|
||||
*/
|
||||
|
||||
#define isleap(y) ((((y) % 4) == 0 && ((y) % 100) != 0) || ((y) % 400) == 0)
|
||||
#define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
|
||||
|
||||
#ifndef USG
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue