*** localtime.c.dist 2009-03-23 06:37:50.000000000 -0700 --- localtime.c 2009-05-17 14:41:52.000000000 -0700 *************** *** 17,22 **** --- 17,23 ---- /*LINTLIBRARY*/ #include "private.h" + #include "xtime.h" #include "tzfile.h" #include "fcntl.h" #include "float.h" /* for FLT_MAX and DBL_MAX */ *************** *** 105,110 **** --- 106,115 ---- #define MY_TZNAME_MAX 255 #endif /* !defined TZNAME_MAX */ + /* + ** Definition of time zone state; this is opaque to callers, which supply + ** pointers to zone state. + */ struct state { int leapcnt; int timecnt; *************** *** 148,156 **** static const char * getrule(const char * strp, struct rule * rulep); static void gmtload(struct state * sp); static struct tm * gmtsub(const time_t * timep, long offset, ! struct tm * tmp); static struct tm * localsub(const time_t * timep, long offset, ! struct tm * tmp); static int increment_overflow(int * number, int delta); static int leaps_thru_end_of(int y); static int long_increment_overflow(long * number, int delta); --- 153,161 ---- static const char * getrule(const char * strp, struct rule * rulep); static void gmtload(struct state * sp); static struct tm * gmtsub(const time_t * timep, long offset, ! struct tm * tmp, const struct state * sp); static struct tm * localsub(const time_t * timep, long offset, ! struct tm * tmp, const struct state * sp); static int increment_overflow(int * number, int delta); static int leaps_thru_end_of(int y); static int long_increment_overflow(long * number, int delta); *************** *** 161,176 **** static void settzname(void); static time_t time1(struct tm * tmp, struct tm * (*funcp)(const time_t *, ! long, struct tm *), ! long offset); static time_t time2(struct tm *tmp, struct tm * (*funcp)(const time_t *, ! long, struct tm*), ! long offset, int * okayp); static time_t time2sub(struct tm *tmp, struct tm * (*funcp)(const time_t *, ! long, struct tm*), ! long offset, int * okayp, int do_norm_secs); static struct tm * timesub(const time_t * timep, long offset, const struct state * sp, struct tm * tmp); static int tmcomp(const struct tm * atmp, --- 166,183 ---- static void settzname(void); static time_t time1(struct tm * tmp, struct tm * (*funcp)(const time_t *, ! long, struct tm *, const struct state *), ! long offset, const struct state *); static time_t time2(struct tm *tmp, struct tm * (*funcp)(const time_t *, ! long, struct tm*, const struct state *), ! long offset, const struct state *, ! int * okayp); static time_t time2sub(struct tm *tmp, struct tm * (*funcp)(const time_t *, ! long, struct tm*, const struct state *), ! long offset, const struct state *, ! int * okayp, int do_norm_secs); static struct tm * timesub(const time_t * timep, long offset, const struct state * sp, struct tm * tmp); static int tmcomp(const struct tm * atmp, *************** *** 1147,1152 **** --- 1154,1196 ---- (void) tzparse(gmt, sp, TRUE); } + zoneinfo_t + loadzone(const char * zonename) + { + struct state * sp; + + sp = (struct state *) malloc(sizeof *sp); + if (sp == NULL) + return NULL; + + if (zonename == NULL) { + if (tzload((char *) NULL, sp, TRUE) != 0) + gmtload(sp); + return sp; + } + if (*zonename == '\0') { + /* + ** User wants it fast rather than right. + */ + sp->leapcnt = 0; /* so, we're off a little */ + sp->timecnt = 0; + sp->typecnt = 0; + sp->ttis[0].tt_isdst = 0; + sp->ttis[0].tt_gmtoff = 0; + sp->ttis[0].tt_abbrind = 0; + (void) strcpy(sp->chars, gmt); + } else if (tzload(zonename, sp, TRUE) != 0) + if (zonename[0] == ':' || tzparse(zonename, sp, FALSE) != 0) + (void) gmtload(lclptr); + return sp; + } + + void + freezone(zoneinfo_t zoneinfo) + { + free(zoneinfo); + } + #ifndef STD_INSPIRED /* ** A non-static declaration of tzsetwall in a system header file *************** *** 1229,1249 **** /*ARGSUSED*/ static struct tm * ! localsub(timep, offset, tmp) ! const time_t * const timep; ! const long offset; ! struct tm * const tmp; { - register struct state * sp; register const struct ttinfo * ttisp; register int i; register struct tm * result; const time_t t = *timep; - sp = lclptr; #ifdef ALL_STATE if (sp == NULL) ! return gmtsub(timep, offset, tmp); #endif /* defined ALL_STATE */ if ((sp->goback && t < sp->ats[0]) || (sp->goahead && t > sp->ats[sp->timecnt - 1])) { --- 1273,1292 ---- /*ARGSUSED*/ static struct tm * ! localsub(timep, offset, tmp, sp) ! const time_t * const timep; ! const long offset; ! struct tm * const tmp; ! const struct state * const sp; { register const struct ttinfo * ttisp; register int i; register struct tm * result; const time_t t = *timep; #ifdef ALL_STATE if (sp == NULL) ! return gmtsub(timep, offset, tmp, NULL); #endif /* defined ALL_STATE */ if ((sp->goback && t < sp->ats[0]) || (sp->goahead && t > sp->ats[sp->timecnt - 1])) { *************** *** 1270,1276 **** if (newt < sp->ats[0] || newt > sp->ats[sp->timecnt - 1]) return NULL; /* "cannot happen" */ ! result = localsub(&newt, offset, tmp); if (result == tmp) { register time_t newy; --- 1313,1319 ---- if (newt < sp->ats[0] || newt > sp->ats[sp->timecnt - 1]) return NULL; /* "cannot happen" */ ! result = localsub(&newt, offset, tmp, sp); if (result == tmp) { register time_t newy; *************** *** 1325,1331 **** const time_t * const timep; { tzset(); ! return localsub(timep, 0L, &tm); } /* --- 1368,1374 ---- const time_t * const timep; { tzset(); ! return localsub(timep, 0L, &tm, lclptr); } /* *************** *** 1337,1343 **** const time_t * const timep; struct tm * tmp; { ! return localsub(timep, 0L, tmp); } /* --- 1380,1400 ---- const time_t * const timep; struct tm * tmp; { ! return localsub(timep, 0L, tmp, lclptr); ! } ! ! /* ! ** Re-entrant version of localtime which takes zone information as ! ** an argument and converts for the specified zone. ! */ ! ! struct tm * ! localtime_zr(timep, tmp, zoneinfo) ! const time_t * const timep; ! struct tm * tmp; ! const zoneinfo_t zoneinfo; ! { ! return localsub(timep, 0L, tmp, zoneinfo); } /* *************** *** 1345,1354 **** */ static struct tm * ! gmtsub(timep, offset, tmp) ! const time_t * const timep; ! const long offset; ! struct tm * const tmp; { register struct tm * result; --- 1402,1412 ---- */ static struct tm * ! gmtsub(timep, offset, tmp, sp) ! const time_t * const timep; ! const long offset; ! struct tm * const tmp; ! const struct state * const sp; { register struct tm * result; *************** *** 1387,1393 **** gmtime(timep) const time_t * const timep; { ! return gmtsub(timep, 0L, &tm); } /* --- 1445,1451 ---- gmtime(timep) const time_t * const timep; { ! return gmtsub(timep, 0L, &tm, NULL); } /* *************** *** 1399,1405 **** const time_t * const timep; struct tm * tmp; { ! return gmtsub(timep, 0L, tmp); } #ifdef STD_INSPIRED --- 1457,1463 ---- const time_t * const timep; struct tm * tmp; { ! return gmtsub(timep, 0L, tmp, NULL); } #ifdef STD_INSPIRED *************** *** 1409,1415 **** const time_t * const timep; const long offset; { ! return gmtsub(timep, offset, &tm); } #endif /* defined STD_INSPIRED */ --- 1467,1473 ---- const time_t * const timep; const long offset; { ! return gmtsub(timep, offset, &tm, NULL); } #endif /* defined STD_INSPIRED */ *************** *** 1672,1685 **** } static time_t ! time2sub(tmp, funcp, offset, okayp, do_norm_secs) struct tm * const tmp; ! struct tm * (* const funcp)(const time_t*, long, struct tm*); const long offset; int * const okayp; const int do_norm_secs; { - register const struct state * sp; register int dir; register int i, j; register int saved_seconds; --- 1730,1744 ---- } static time_t ! time2sub(tmp, funcp, offset, sp, okayp, do_norm_secs) struct tm * const tmp; ! struct tm * (* const funcp)(const time_t*, long, struct tm*, ! const struct state *); const long offset; + const struct state * sp; int * const okayp; const int do_norm_secs; { register int dir; register int i, j; register int saved_seconds; *************** *** 1781,1787 **** t = lo; else if (t > hi) t = hi; ! if ((*funcp)(&t, offset, &mytm) == NULL) { /* ** Assume that t is too extreme to be represented in ** a struct tm; arrange things so that it is less --- 1840,1846 ---- t = lo; else if (t > hi) t = hi; ! if ((*funcp)(&t, offset, &mytm, sp) == NULL) { /* ** Assume that t is too extreme to be represented in ** a struct tm; arrange things so that it is less *************** *** 1816,1823 **** ** It's okay to guess wrong since the guess ** gets checked. */ - sp = (const struct state *) - ((funcp == localsub) ? lclptr : gmtptr); #ifdef ALL_STATE if (sp == NULL) return WRONG; --- 1875,1880 ---- *************** *** 1830,1836 **** continue; newt = t + sp->ttis[j].tt_gmtoff - sp->ttis[i].tt_gmtoff; ! if ((*funcp)(&newt, offset, &mytm) == NULL) continue; if (tmcomp(&mytm, &yourtm) != 0) continue; --- 1887,1893 ---- continue; newt = t + sp->ttis[j].tt_gmtoff - sp->ttis[i].tt_gmtoff; ! if ((*funcp)(&newt, offset, &mytm, sp) == NULL) continue; if (tmcomp(&mytm, &yourtm) != 0) continue; *************** *** 1850,1865 **** if ((newt < t) != (saved_seconds < 0)) return WRONG; t = newt; ! if ((*funcp)(&t, offset, tmp)) *okayp = TRUE; return t; } static time_t ! time2(tmp, funcp, offset, okayp) struct tm * const tmp; ! struct tm * (* const funcp)(const time_t*, long, struct tm*); const long offset; int * const okayp; { time_t t; --- 1907,1924 ---- if ((newt < t) != (saved_seconds < 0)) return WRONG; t = newt; ! if ((*funcp)(&t, offset, tmp, sp)) *okayp = TRUE; return t; } static time_t ! time2(tmp, funcp, offset, sp, okayp) struct tm * const tmp; ! struct tm * (* const funcp)(const time_t*, long, struct tm*, ! const struct state *); const long offset; + const struct state * sp; int * const okayp; { time_t t; *************** *** 1869,1886 **** ** (in case tm_sec contains a value associated with a leap second). ** If that fails, try with normalization of seconds. */ ! t = time2sub(tmp, funcp, offset, okayp, FALSE); ! return *okayp ? t : time2sub(tmp, funcp, offset, okayp, TRUE); } static time_t ! time1(tmp, funcp, offset) struct tm * const tmp; ! struct tm * (* const funcp)(const time_t *, long, struct tm *); const long offset; { register time_t t; - register const struct state * sp; register int samei, otheri; register int sameind, otherind; register int i; --- 1928,1946 ---- ** (in case tm_sec contains a value associated with a leap second). ** If that fails, try with normalization of seconds. */ ! t = time2sub(tmp, funcp, offset, sp, okayp, FALSE); ! return *okayp ? t : time2sub(tmp, funcp, offset, sp, okayp, TRUE); } static time_t ! time1(tmp, funcp, offset, sp) struct tm * const tmp; ! struct tm * (* const funcp)(const time_t *, long, struct tm *, ! const struct state *); const long offset; + const struct state * sp; { register time_t t; register int samei, otheri; register int sameind, otherind; register int i; *************** *** 1891,1897 **** if (tmp->tm_isdst > 1) tmp->tm_isdst = 1; ! t = time2(tmp, funcp, offset, &okay); #ifdef PCTS /* ** PCTS code courtesy Grant Sullivan. --- 1951,1957 ---- if (tmp->tm_isdst > 1) tmp->tm_isdst = 1; ! t = time2(tmp, funcp, offset, sp, &okay); #ifdef PCTS /* ** PCTS code courtesy Grant Sullivan. *************** *** 1911,1917 **** ** We try to divine the type they started from and adjust to the ** type they need. */ - sp = (const struct state *) ((funcp == localsub) ? lclptr : gmtptr); #ifdef ALL_STATE if (sp == NULL) return WRONG; --- 1971,1976 ---- *************** *** 1935,1941 **** tmp->tm_sec += sp->ttis[otheri].tt_gmtoff - sp->ttis[samei].tt_gmtoff; tmp->tm_isdst = !tmp->tm_isdst; ! t = time2(tmp, funcp, offset, &okay); if (okay) return t; tmp->tm_sec -= sp->ttis[otheri].tt_gmtoff - --- 1994,2000 ---- tmp->tm_sec += sp->ttis[otheri].tt_gmtoff - sp->ttis[samei].tt_gmtoff; tmp->tm_isdst = !tmp->tm_isdst; ! t = time2(tmp, funcp, offset, sp, &okay); if (okay) return t; tmp->tm_sec -= sp->ttis[otheri].tt_gmtoff - *************** *** 1951,1957 **** struct tm * const tmp; { tzset(); ! return time1(tmp, localsub, 0L); } #ifdef STD_INSPIRED --- 2010,2024 ---- struct tm * const tmp; { tzset(); ! return time1(tmp, localsub, 0L, lclptr); ! } ! ! time_t ! mktime_z(tmp, zoneinfo) ! struct tm * const tmp; ! const zoneinfo_t zoneinfo; ! { ! return time1(tmp, localsub, 0L, zoneinfo); } #ifdef STD_INSPIRED *************** *** 1969,1975 **** struct tm * const tmp; { tmp->tm_isdst = 0; ! return time1(tmp, gmtsub, 0L); } time_t --- 2036,2042 ---- struct tm * const tmp; { tmp->tm_isdst = 0; ! return time1(tmp, gmtsub, 0L, gmtptr); } time_t *************** *** 1978,1984 **** const long offset; { tmp->tm_isdst = 0; ! return time1(tmp, gmtsub, offset); } #endif /* defined STD_INSPIRED */ --- 2045,2051 ---- const long offset; { tmp->tm_isdst = 0; ! return time1(tmp, gmtsub, offset, gmtptr); } #endif /* defined STD_INSPIRED */ *** newctime.3.dist 2009-03-23 06:37:49.000000000 -0700 --- newctime.3 2009-05-20 17:28:41.000000000 -0700 *************** *** 30,35 **** --- 30,52 ---- .B time_t mktime(tm) .B struct tm *tm; .PP + .B #include + .PP + .B zoneinfo_t loadzone(zonename) + .B const char *zonename; + .PP + .B void freezone(zoneinfo) + .B zoneinfo_t zoneinfo; + .PP + .B struct tm *localtime_zr(clock, tm, zoneinfo) + .B const time_t *clock; + .B struct tm *tm; + .B const zoneinfo_t zoneinfo; + .PP + .B time_t mktime_z(tm, zoneinfo) + .B struct tm *tm; + .B const zoneinfo_t zoneinfo; + .PP .B cc ... -ltz .fi .SH DESCRIPTION *************** *** 137,142 **** --- 154,191 ---- it returns .BR -1 . .PP + .I Loadzone\^ + allocates a structure to hold time zone information and fills it in with + information for the time zone specified by + .IR zonename . + It returns a pointer to that structure. + .PP + .I Freezone\^ + frees the time zone information structure pointed to by + .IR zoneinfo . + .PP + .I Localtime_zr\^ + fills in the ``tm'' structure pointed to by + .I tm + for the time specified by + .I clock + in the time zone specified by + .IR zoneinfo . + It returns a pointer to + .I tm + on success and NULL on failure. + .PP + .I Mktime_z\^ + converts the broken-down time, expresed as local time in the zone + specified by + .I zoneinfo , + in the structure pointed to by + .I tm + into a calendar time value with the same encoding as that of the values + returned by the + .I time + function. + .PP .I Difftime\^ returns the difference between two calendar times, .RI ( time1 *** Makefile.dist 2009-03-23 06:37:49.000000000 -0700 --- Makefile 2009-05-20 17:40:45.000000000 -0700 *************** *** 59,64 **** --- 59,68 ---- LIBDIR= $(TOPDIR)/lib TZLIB= $(LIBDIR)/libtz.a + # Header files go in. . . + + INCDIR= $(TOPDIR)/include + # If you always want time values interpreted as "seconds since the epoch # (not counting leap seconds)", use # REDO= posix_only *************** *** 342,352 **** zones: $(REDO) ! $(TZLIB): $(LIBOBJS) -mkdir $(TOPDIR) $(LIBDIR) ar ru $@ $(LIBOBJS) if [ -x /usr/ucb/ranlib -o -x /usr/bin/ranlib ] ; \ then ranlib $@ ; fi date: $(DATEOBJS) $(CC) $(CFLAGS) date.o localtime.o asctime.o strftime.o \ --- 346,358 ---- zones: $(REDO) ! $(TZLIB): $(LIBOBJS) xtime.h -mkdir $(TOPDIR) $(LIBDIR) ar ru $@ $(LIBOBJS) if [ -x /usr/ucb/ranlib -o -x /usr/bin/ranlib ] ; \ then ranlib $@ ; fi + -rm -f $(INCDIR)/xtime.h + cp xtime.h $(INCDIR) date: $(DATEOBJS) $(CC) $(CFLAGS) date.o localtime.o asctime.o strftime.o \