diff --git a/libc/time/lib_localtime.c b/libc/time/lib_localtime.c index ff0f0aa82d9..26f0c17ce09 100644 --- a/libc/time/lib_localtime.c +++ b/libc/time/lib_localtime.c @@ -48,6 +48,8 @@ * Included Files ****************************************************************************/ +#include + #include #include #include @@ -56,11 +58,84 @@ #include #include -#include "tzfile.h" - /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ +/* Configuration ************************************************************/ +/* Time zone object file directory */ + +#ifdef CONFIG_LIBC_TZ_TZDIR +# define TZDIR CONFIG_LIBC_TZ_TZDIR +#else +# define TZDIR "/usr/local/etc/zoneinfo" +#endif + +/* Time definitions *********************************************************/ + +/* Time zone files */ + +#define TZ_MAGIC "TZif" +#define TZDEFAULT "localtime" +#define TZDEFRULES "posixrules" + +/* In the current implementation, "tzset()" refuses to deal with files that + * exceed any of the limits below. + */ + +#define TZ_MAX_CHARS 50 /* Maximum number of abbreviation characters */ +#define TZ_MAX_LEAPS 50 /* Maximum number of leap second corrections */ + +#define SECSPERMIN 60 +#define MINSPERHOUR 60 +#define HOURSPERDAY 24 +#define DAYSPERWEEK 7 +#define DAYSPERNYEAR 365 +#define DAYSPERLYEAR 366 +#define SECSPERHOUR (SECSPERMIN * MINSPERHOUR) +#define SECSPERDAY ((int_fast32_t) SECSPERHOUR * HOURSPERDAY) +#define MONSPERYEAR 12 + +#define TM_SUNDAY 0 +#define TM_MONDAY 1 +#define TM_TUESDAY 2 +#define TM_WEDNESDAY 3 +#define TM_THURSDAY 4 +#define TM_FRIDAY 5 +#define TM_SATURDAY 6 + +#define TM_JANUARY 0 +#define TM_FEBRUARY 1 +#define TM_MARCH 2 +#define TM_APRIL 3 +#define TM_MAY 4 +#define TM_JUNE 5 +#define TM_JULY 6 +#define TM_AUGUST 7 +#define TM_SEPTEMBER 8 +#define TM_OCTOBER 9 +#define TM_NOVEMBER 10 +#define TM_DECEMBER 11 + +#define TM_YEAR_BASE 1900 + +#define EPOCH_YEAR 1970 +#define EPOCH_WDAY TM_THURSDAY + +#define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0)) + +/* Since everything in isleap is modulo 400 (or a factor of 400), we know that + * isleap(y) == isleap(y % 400) + * and so + * isleap(a + b) == isleap((a + b) % 400) + * or + * isleap(a + b) == isleap(a % 400 + b % 400) + * + * This is true even if % means modulo rather than Fortran remainder (which + * is allowed by C89 but not C99). We use this to avoid addition overflow + * problems. + */ + +#define isleap_sum(a, b) isleap((a) % 400 + (b) % 400) #define GRANDPARENTED "Local time zone must be set--see zic manual page" #define TYPE_BIT(type) (sizeof (type) * CHAR_BIT) @@ -125,6 +200,58 @@ * Private Types ****************************************************************************/ +/* Time file file header. + * Each time zone file begins with a time zone header followed by: + * + * tzh_timecnt (char [4])s coded transition times a la time(2) + * tzh_timecnt (unsigned char)s types of local time starting at above + * tzh_typecnt repetitions of + * one (char [4]) coded UT offset in seconds + * one (unsigned char) used to set tm_isdst + * one (unsigned char) that's an abbreviation list index + * tzh_charcnt (char)s '\0'-terminated zone abbreviations + * tzh_leapcnt repetitions of + * one (char [4]) coded leap second transition times + * one (char [4]) total correction after above + * tzh_ttisstdcnt (char)s indexed by type; if TRUE, transition + * time is standard time, if FALSE, + * 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 UT, if FALSE, + * transition time is local time + * if absent, transition times are + * assumed to be local time + * + * If tzh_version is '2' or greater, the above is followed by a second + * instance of tzhead_s and a second instance of the data in which each + * coded transition time uses 8 rather than 4 chars, then a + * POSIX-TZ-environment-variable-style string for use in handling instants + * after the last transition time stored in the file (with nothing between + * the newlines if there is no POSIX representation for such instants). + * + * If tz_version is '3' or greater, the above is extended as follows. + * First, the POSIX TZ string's hour offset may range from -167 through + * 167 as compared to the POSIX-required 0 through 24. Second, its DST + * start time may be January 1 at 00:00 and its stop time December 31 at + * 24:00 plus the difference between DST and standard time, indicating DST + * all year. + */ + +struct tzhead_s +{ + char tzh_magic[4]; /* TZ_MAGIC */ + char tzh_version[1]; /* '\0' or '2' or '3' as of 2013 */ + char tzh_reserved[15]; /* reserved; must be zero */ + 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 */ + char tzh_typecnt[4]; /* coded number of local time types */ + char tzh_charcnt[4]; /* coded number of abbr. chars */ +}; + struct ttinfo_s { /* Time type information */ int_fast32_t tt_gmtoff; /* UT offset in seconds */ @@ -370,8 +497,8 @@ static int tzload(FAR const char *name, typedef union { - struct tzhead tzhead; - char buf[2 * sizeof(struct tzhead) + 2 * sizeof *sp + 4 * TZ_MAX_TIMES]; + struct tzhead_s tzhead_s; + char buf[2 * sizeof(struct tzhead_s) + 2 * sizeof *sp + 4 * TZ_MAX_TIMES]; } u_t; union local_storage @@ -469,14 +596,14 @@ static int tzload(FAR const char *name, int ttisgmtcnt; int timecnt; - ttisstdcnt = (int)detzcode(up->tzhead.tzh_ttisstdcnt); - ttisgmtcnt = (int)detzcode(up->tzhead.tzh_ttisgmtcnt); - sp->leapcnt = (int)detzcode(up->tzhead.tzh_leapcnt); - sp->timecnt = (int)detzcode(up->tzhead.tzh_timecnt); - sp->typecnt = (int)detzcode(up->tzhead.tzh_typecnt); - sp->charcnt = (int)detzcode(up->tzhead.tzh_charcnt); + ttisstdcnt = (int)detzcode(up->tzhead_s.tzh_ttisstdcnt); + ttisgmtcnt = (int)detzcode(up->tzhead_s.tzh_ttisgmtcnt); + sp->leapcnt = (int)detzcode(up->tzhead_s.tzh_leapcnt); + sp->timecnt = (int)detzcode(up->tzhead_s.tzh_timecnt); + sp->typecnt = (int)detzcode(up->tzhead_s.tzh_typecnt); + sp->charcnt = (int)detzcode(up->tzhead_s.tzh_charcnt); - p = up->tzhead.tzh_charcnt + sizeof up->tzhead.tzh_charcnt; + p = up->tzhead_s.tzh_charcnt + sizeof up->tzhead_s.tzh_charcnt; 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 || @@ -616,7 +743,7 @@ static int tzload(FAR const char *name, /* If this is an old file, we're done. */ - if (up->tzhead.tzh_version[0] == '\0') + if (up->tzhead_s.tzh_version[0] == '\0') { break; } diff --git a/libc/time/tzfile.h b/libc/time/tzfile.h deleted file mode 100644 index dad3be9973f..00000000000 --- a/libc/time/tzfile.h +++ /dev/null @@ -1,173 +0,0 @@ -#ifndef TZFILE_H - -#define TZFILE_H - -/* -** This file is in the public domain, so clarified as of -** 1996-06-05 by Arthur David Olson. -*/ - -/* -** This header is for use ONLY with the time conversion code. -** There is no guarantee that it will remain unchanged, -** or that it will remain at all. -** Do NOT copy it to any system include directory. -** Thank you! -*/ - -/* -** Information about time zone files. -*/ - -#ifdef CONFIG_LIBC_TZDIR -#define TZDIR CONFIG_LIBC_TZDIR -#endif - -#ifndef TZDIR -#define TZDIR "/usr/local/etc/zoneinfo" /* Time zone object file directory */ -#endif /* !defined TZDIR */ - -#ifndef TZDEFAULT -#define TZDEFAULT "localtime" -#endif /* !defined TZDEFAULT */ - -#ifndef TZDEFRULES -#define TZDEFRULES "posixrules" -#endif /* !defined TZDEFRULES */ - -/* -** Each file begins with. . . -*/ - -#define TZ_MAGIC "TZif" - -struct tzhead { - char tzh_magic[4]; /* TZ_MAGIC */ - char tzh_version[1]; /* '\0' or '2' or '3' as of 2013 */ - char tzh_reserved[15]; /* reserved; must be zero */ - 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 */ - char tzh_typecnt[4]; /* coded number of local time types */ - char tzh_charcnt[4]; /* coded number of abbr. chars */ -}; - -/* -** . . .followed by. . . -** -** tzh_timecnt (char [4])s coded transition times a la time(2) -** tzh_timecnt (unsigned char)s types of local time starting at above -** tzh_typecnt repetitions of -** one (char [4]) coded UT offset in seconds -** one (unsigned char) used to set tm_isdst -** one (unsigned char) that's an abbreviation list index -** tzh_charcnt (char)s '\0'-terminated zone abbreviations -** tzh_leapcnt repetitions of -** one (char [4]) coded leap second transition times -** one (char [4]) total correction after above -** tzh_ttisstdcnt (char)s indexed by type; if TRUE, transition -** time is standard time, if FALSE, -** 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 UT, if FALSE, -** transition time is local time -** if absent, transition times are -** assumed to be local time -*/ - -/* -** If tzh_version is '2' or greater, the above is followed by a second instance -** of tzhead and a second instance of the data in which each coded transition -** time uses 8 rather than 4 chars, -** then a POSIX-TZ-environment-variable-style string for use in handling -** instants after the last transition time stored in the file -** (with nothing between the newlines if there is no POSIX representation for -** such instants). -** -** If tz_version is '3' or greater, the above is extended as follows. -** First, the POSIX TZ string's hour offset may range from -167 -** through 167 as compared to the POSIX-required 0 through 24. -** Second, its DST start time may be January 1 at 00:00 and its stop -** time December 31 at 24:00 plus the difference between DST and -** standard time, indicating DST all year. -*/ - -/* -** In the current implementation, "tzset()" refuses to deal with files that -** exceed any of the limits below. -*/ - -#ifndef TZ_MAX_TIMES -#define TZ_MAX_TIMES 2000 -#endif /* !defined TZ_MAX_TIMES */ - -#ifndef TZ_MAX_TYPES -/* This must be at least 17 for Europe/Samara and Europe/Vilnius. */ -#define TZ_MAX_TYPES 256 /* Limited by what (unsigned char)'s can hold */ -#endif /* !defined TZ_MAX_TYPES */ - -#ifndef TZ_MAX_CHARS -#define TZ_MAX_CHARS 50 /* Maximum number of abbreviation characters */ - /* (limited by what unsigned chars can hold) */ -#endif /* !defined TZ_MAX_CHARS */ - -#ifndef TZ_MAX_LEAPS -#define TZ_MAX_LEAPS 50 /* Maximum number of leap second corrections */ -#endif /* !defined TZ_MAX_LEAPS */ - -#define SECSPERMIN 60 -#define MINSPERHOUR 60 -#define HOURSPERDAY 24 -#define DAYSPERWEEK 7 -#define DAYSPERNYEAR 365 -#define DAYSPERLYEAR 366 -#define SECSPERHOUR (SECSPERMIN * MINSPERHOUR) -#define SECSPERDAY ((int_fast32_t) SECSPERHOUR * HOURSPERDAY) -#define MONSPERYEAR 12 - -#define TM_SUNDAY 0 -#define TM_MONDAY 1 -#define TM_TUESDAY 2 -#define TM_WEDNESDAY 3 -#define TM_THURSDAY 4 -#define TM_FRIDAY 5 -#define TM_SATURDAY 6 - -#define TM_JANUARY 0 -#define TM_FEBRUARY 1 -#define TM_MARCH 2 -#define TM_APRIL 3 -#define TM_MAY 4 -#define TM_JUNE 5 -#define TM_JULY 6 -#define TM_AUGUST 7 -#define TM_SEPTEMBER 8 -#define TM_OCTOBER 9 -#define TM_NOVEMBER 10 -#define TM_DECEMBER 11 - -#define TM_YEAR_BASE 1900 - -#define EPOCH_YEAR 1970 -#define EPOCH_WDAY TM_THURSDAY - -#define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0)) - -/* -** Since everything in isleap is modulo 400 (or a factor of 400), we know that -** isleap(y) == isleap(y % 400) -** and so -** isleap(a + b) == isleap((a + b) % 400) -** or -** isleap(a + b) == isleap(a % 400 + b % 400) -** This is true even if % means modulo rather than Fortran remainder -** (which is allowed by C89 but not C99). -** We use this to avoid addition overflow problems. -*/ - -#define isleap_sum(a, b) isleap((a) % 400 + (b) % 400) - -#endif /* !defined TZFILE_H */