Module Name: src
Committed By: christos
Date: Thu Dec 16 18:38:07 UTC 2010
Modified Files:
src/lib/libc: shlib_version
src/lib/libc/compat/include: time.h
src/lib/libc/include: namespace.h
src/lib/libc/time: Makefile.inc ctime.3 localtime.c offtime.3
strftime.3 strftime.c time2posix.3
Log Message:
Provide a re-entrant and thread-safe set of timezone API's that
don't require locking and can operate on user-specified timezones
as opposed to having to alter the environment to change a timezone.
This work was presented to the tzcode folks and it was generally
accepted, but there seems to be a lot of inertia.
To generate a diff of this commit:
cvs rdiff -u -r1.219 -r1.220 src/lib/libc/shlib_version
cvs rdiff -u -r1.2 -r1.3 src/lib/libc/compat/include/time.h
cvs rdiff -u -r1.145 -r1.146 src/lib/libc/include/namespace.h
cvs rdiff -u -r1.13 -r1.14 src/lib/libc/time/Makefile.inc
cvs rdiff -u -r1.35 -r1.36 src/lib/libc/time/ctime.3
cvs rdiff -u -r1.48 -r1.49 src/lib/libc/time/localtime.c
cvs rdiff -u -r1.1 -r1.2 src/lib/libc/time/offtime.3
cvs rdiff -u -r1.26 -r1.27 src/lib/libc/time/strftime.3
cvs rdiff -u -r1.20 -r1.21 src/lib/libc/time/strftime.c
cvs rdiff -u -r1.15 -r1.16 src/lib/libc/time/time2posix.3
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/lib/libc/shlib_version
diff -u src/lib/libc/shlib_version:1.219 src/lib/libc/shlib_version:1.220
--- src/lib/libc/shlib_version:1.219 Fri Sep 24 05:21:53 2010
+++ src/lib/libc/shlib_version Thu Dec 16 13:38:06 2010
@@ -1,4 +1,4 @@
-# $NetBSD: shlib_version,v 1.219 2010/09/24 09:21:53 tnozaki Exp $
+# $NetBSD: shlib_version,v 1.220 2010/12/16 18:38:06 christos Exp $
# Remember to update distrib/sets/lists/base/shl.* when changing
#
# things we wish to do on next major version bump:
@@ -31,4 +31,4 @@
# it's insufficient bitwidth to implement all ctype class.
# see isblank's comment in ctype.h.
major=12
-minor=174
+minor=175
Index: src/lib/libc/compat/include/time.h
diff -u src/lib/libc/compat/include/time.h:1.2 src/lib/libc/compat/include/time.h:1.3
--- src/lib/libc/compat/include/time.h:1.2 Sat Jan 10 21:46:25 2009
+++ src/lib/libc/compat/include/time.h Thu Dec 16 13:38:06 2010
@@ -1,4 +1,4 @@
-/* $NetBSD: time.h,v 1.2 2009/01/11 02:46:25 christos Exp $ */
+/* $NetBSD: time.h,v 1.3 2010/12/16 18:38:06 christos Exp $ */
/*
* Copyright (c) 1989, 1993
@@ -86,9 +86,21 @@
struct tm *gmtime_r(const int32_t * __restrict, struct tm * __restrict);
struct tm *localtime_r(const int32_t * __restrict, struct tm * __restrict);
struct tm *offtime(const int32_t *, long);
+struct tm *offtime_r(const int32_t *, long, struct tm *);
int32_t timelocal(struct tm *);
int32_t timegm(struct tm *);
int32_t timeoff(struct tm *, long);
int32_t time2posix(int32_t);
int32_t posix2time(int32_t);
+struct tm *localtime_rz(const timezone_t, const int32_t * __restrict,
+ struct tm * __restrict);
+char *ctime_rz(const timezone_t, const int32_t *, char *);
+int32_t mktime_z(const timezone_t, struct tm *);
+int32_t timelocal_z(const timezone_t, struct tm *);
+int32_t time2posix_z(const timezone_t, int32_t);
+int32_t posix2time_z(const timezone_t, int32_t);
+timezone_t tzalloc(const char *);
+void tzfree(const timezone_t);
+const char *tzgetname(const timezone_t, int);
+
#endif /* !_COMPAT_TIME_H_ */
Index: src/lib/libc/include/namespace.h
diff -u src/lib/libc/include/namespace.h:1.145 src/lib/libc/include/namespace.h:1.146
--- src/lib/libc/include/namespace.h:1.145 Wed Nov 17 08:19:32 2010
+++ src/lib/libc/include/namespace.h Thu Dec 16 13:38:06 2010
@@ -1,4 +1,4 @@
-/* $NetBSD: namespace.h,v 1.145 2010/11/17 13:19:32 tron Exp $ */
+/* $NetBSD: namespace.h,v 1.146 2010/12/16 18:38:06 christos Exp $ */
/*-
* Copyright (c) 1997-2004 The NetBSD Foundation, Inc.
@@ -221,6 +221,7 @@
#define csetexpandtc _csetexpandtc
#define ctermid _ctermid
#define ctime_r _ctime_r
+#define ctime_rz _ctime_rz
#define daemon _daemon
#define dbopen _dbopen
#define devname _devname
@@ -432,12 +433,14 @@
#define llabs _llabs
#define lldiv _lldiv
#define localtime_r _localtime_r
+#define localtime_rz _localtime_rz
#define lockf _lockf
#define lrand48 _lrand48
#define lseek _lseek
#define mergesort _mergesort
#define mi_vector_hash _mi_vector_hash
#define mkstemp _mkstemp
+#define mktime_z _mktime_z
#define mmap _mmap
#define mpool_close _mpool_close
#define mpool_filter _mpool_filter
@@ -474,6 +477,7 @@
#define pollts _pollts
#define popen _popen
#define posix2time _posix2time
+#define posix2time_z _posix2time_z
#define pread _pread
#define pselect _pselect
#define psignal _psignal
@@ -579,6 +583,7 @@
#define strcasecmp _strcasecmp
#define strdup _strdup
#define stresep _stresep
+#define strftime_z _strftime_z
#define strndup _strndup
#define strncasecmp _strncasecmp
#define strptime _strptime
Index: src/lib/libc/time/Makefile.inc
diff -u src/lib/libc/time/Makefile.inc:1.13 src/lib/libc/time/Makefile.inc:1.14
--- src/lib/libc/time/Makefile.inc:1.13 Thu May 14 22:23:42 2009
+++ src/lib/libc/time/Makefile.inc Thu Dec 16 13:38:07 2010
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile.inc,v 1.13 2009/05/15 02:23:42 jakllsch Exp $
+# $NetBSD: Makefile.inc,v 1.14 2010/12/16 18:38:07 christos Exp $
.PATH: ${.CURDIR}/time
@@ -9,6 +9,7 @@
CPPFLAGS+=-DALL_STATE -DUSG_COMPAT
MLINKS+=ctime.3 ctime_r.3 \
+ ctime.3 ctime_rz.3 \
ctime.3 asctime.3 \
ctime.3 asctime_r.3 \
ctime.3 difftime.3 \
@@ -16,10 +17,17 @@
ctime.3 gmtime_r.3 \
ctime.3 localtime.3 \
ctime.3 localtime_r.3 \
+ ctime.3 localtime_rz.3 \
ctime.3 mktime.3 \
+ ctime.3 mktime_z.3 \
getdate.3 getdate_err.3 \
+ offtime.3 offtime_r.3 \
offtime.3 timeoff.3 \
offtime.3 timegm.3 \
offtime.3 timelocal.3 \
+ time2posix.3 posix2time.3 \
+ time2posix.3 posix2time_z.3 \
+ time2posix.3 time2posix_z.3 \
tzset.3 daylight.3 \
- tzset.3 tzsetwall.3
+ tzset.3 tzsetwall.3 \
+ strftime.3 strftime_z.3
Index: src/lib/libc/time/ctime.3
diff -u src/lib/libc/time/ctime.3:1.35 src/lib/libc/time/ctime.3:1.36
--- src/lib/libc/time/ctime.3:1.35 Thu Dec 9 04:22:31 2010
+++ src/lib/libc/time/ctime.3 Thu Dec 16 13:38:07 2010
@@ -1,5 +1,5 @@
-.\" $NetBSD: ctime.3,v 1.35 2010/12/09 09:22:31 njoly Exp $
-.Dd October 27, 2010
+.\" $NetBSD: ctime.3,v 1.36 2010/12/16 18:38:07 christos Exp $
+.Dd December 14, 2010
.Dt CTIME 3
.Os
.Sh NAME
@@ -7,22 +7,30 @@
.Nm asctime_r ,
.Nm ctime ,
.Nm ctime_r ,
+.Nm ctime_rz ,
.Nm difftime ,
.Nm gmtime ,
.Nm gmtime_r ,
.Nm localtime ,
.Nm localtime_r ,
-.Nm mktime
+.Nm localtime_rz ,
+.Nm mktime ,
+.Nm mktime_z ,
+.Nm tzalloc ,
+.Nm tzgetname ,
+.Nm tzfree ,
.Nd convert date and time to ASCII
.Sh LIBRARY
.Lb libc
.Sh SYNOPSIS
.In time.h
-.Vt extern char *tzname[2];
+.Dv extern char *tzname[2];
.Ft char *
.Fn ctime "const time_t *clock"
.Ft char *
.Fn ctime_r "const time_t *clock" "char *buf"
+.Ft char *
+.Fn ctime_rz "const timezone_t tz" "const time_t *clock" "char *buf"
.Ft double
.Fn difftime "time_t time1" "time_t time0"
.Ft char *
@@ -34,15 +42,25 @@
.Ft struct tm *
.Fn localtime_r "const time_t * restrict clock" "struct tm * restrict result"
.Ft struct tm *
+.Fn localtime_rz "const timezone_t tz" "const time_t * restrict clock" "struct tm * restrict result"
+.Ft struct tm *
.Fn gmtime "const time_t *clock"
.Ft struct tm *
.Fn gmtime_r "const time_t * restrict clock" "struct tm * restrict result"
.Ft time_t
.Fn mktime "struct tm *tm"
+.Ft time_t
+.Fn mktime_z "const timezone_t tz" "struct tm *tm"
+.Ft timezone_t
+.Fn tzalloc "const char *zone"
+.Ft const char *
+.Fn tzgetname "const timezone_t tz" "int isdst"
+.Ft void
+.Fn tzfree "const timezone_t tz"
.Sh DESCRIPTION
.Fn ctime
-converts a
-.Vt time_t ,
+converts a
+.Tp time_t ,
pointed to by
.Fa clock ,
representing the time in seconds since
@@ -61,11 +79,19 @@
.Fn ctime_r
is similar to
.Fn ctime ,
-except it places the result of the conversion on the
+except it places the result of the convertion on the
.Fa buf
argument which should be 26 or more bytes long, instead of using a global
static buffer.
.Pp
+.Fn ctime_rz
+is similar to
+.Fn ctime_r ,
+but it also takes a
+.Ft "const timezone_t"
+argument, returned by a previous call to
+.Fn tzalloc .
+.Pp
.Fn localtime
and
.Fn gmtime
@@ -107,10 +133,17 @@
the application may need to do so by calling
.Xr tzset 3 .
.Pp
+.Fn localtime_rz
+is similar to
+.Fn localtime_r ,
+but it also takes a
+.Ft "const timezone_t"
+argument, returned by a previous call to
+.Fn tzalloc .
+.Pp
.Fn asctime
converts a time value contained in a
-.Dq tm
-structure to a string,
+``tm'' structure to a string,
as shown in the above example,
and returns a pointer to the string.
.Pp
@@ -163,11 +196,60 @@
represented, it returns
.Va "(time_t)-1" .
.Pp
+.Fn mktime_z
+is similar to
+.Fn mktime
+but it also takes a
+.Ft "const timezone_t"
+argument, returned by a previous call to
+.Fn tzalloc .
+.Pp
.Fn difftime
returns the difference between two calendar times,
.Fa ( time1 No - Fa time0 ) ,
expressed in seconds.
.Pp
+.Fn tzalloc
+takes as an argument a timezone name and returns a
+.Ft timezone_t
+object suitable to be used in
+.Fn ctime_rz ,
+.Fn localtime_rz ,
+and
+.Fn mktime_z .
+Instead of setting the environment variable
+.Va TZ ,
+and globally changing the behavior of the calling program, one can use
+multiple timezones at the same time by using separate
+.Ft timezone_t
+objects allocated by
+.Fn tzalloc
+and calling the
+.Dq z
+variants of the functions.
+.Pp
+.Fn tzgetname
+returns the name for the given
+.Fa tz .
+If
+.Fa isdst
+is
+.Va 0 ,
+the call is equivalent to
+.Va tzname[0] .
+If
+.Fa isdst
+is set to
+.Va 1
+the call is equivalent to
+.Va tzname[1] .
+.Pp
+.Fn tzfree
+frees the
+.Fa tz
+argument previously returned by
+.Fa tzalloc .
+.Pp
The structure (of type)
.Va "struct tm"
includes the following fields:
@@ -194,6 +276,17 @@
created.
There is no guarantee that these fields will continue to exist
in this form in future releases of this code.
+The
+.Fa tm_zone
+field will become invalid and point to freed storage if the corresponding
+.Va "struct tm"
+was returned by
+.Fn localtime_rz
+and the
+.Ft "const timezone_t"
+.Fa tz
+argument has been freed by
+.Fn tzfree .
.Pp
.Fa tm_isdst
is non-zero if summer time is in effect.
@@ -208,9 +301,10 @@
and
.Fn ctime
functions return a pointer to a static character buffer, and the
-.Fn asctime_r
+.Fn asctime_r ,
+.Fn ctime_r ,
and
-.Fn ctime_r
+.Fn ctime_rz
function return a pointer to the user-supplied buffer.
On failure they all return
.Dv NULL
@@ -222,9 +316,10 @@
functions return a pointer to a statically allocated
.Va "struct tm"
whereas the
-.Fn gmtime_r
+.Fn gmtime_r ,
+.Fn localtime_r ,
and
-.Fn localtime_r
+.Fn localtime_rz ,
functions return a pointer to the user-supplied
.Va "struct tm" .
On failure they all return
@@ -234,16 +329,32 @@
is set to indicate the error.
The
.Fn mktime
+and
+.Fn mktime_z
function returns the specified time since the Epoch as a
-.Vt time_t
+.Va time_t
type value.
If the time cannot be represented, then
.Fn mktime
-returns
+and
+.Fn mktime_z
+return
.Va "(time_t)-1"
setting the global variable
.Va errno
to indicate the error.
+The
+.Fn tzalloc
+function returns a pointer to a
+.Ft timezone_t
+object or
+.Dv NULL
+on failure, setting
+.Va errno
+to indicate the error.
+.Fn tzgetzone
+function returns string containing the name of the timezone given in
+.Fa tz .
.Sh FILES
.Bl -tag -width /usr/share/zoneinfo/posixrules -compact
.It Pa /etc/localtime
@@ -264,15 +375,27 @@
The
.Fn gmtime_r ,
.Fn localtime_r ,
+.Fn localtime_rz ,
.Fn gmtime ,
.Fn localtime ,
and
-.Fn mktime
+.Fn mktime ,
+and
+.Fn mktime_z
will fail when:
.Bl -tag -width Er
.It Bq Er EOVERFLOW
The result cannot be represented.
+.It Bq Er EINVAL
+The result cannot be represented.
.El
+.Pp
+All functions that return values except their
+.Dq z
+variants, can also return the same errors as
+.Xr open 2
+and
+.Xr malloc 3 .
.Sh SEE ALSO
.Xr getenv 3 ,
.Xr strftime 3 ,
Index: src/lib/libc/time/localtime.c
diff -u src/lib/libc/time/localtime.c:1.48 src/lib/libc/time/localtime.c:1.49
--- src/lib/libc/time/localtime.c:1.48 Tue Mar 23 16:28:58 2010
+++ src/lib/libc/time/localtime.c Thu Dec 16 13:38:07 2010
@@ -1,4 +1,4 @@
-/* $NetBSD: localtime.c,v 1.48 2010/03/23 20:28:58 drochner Exp $ */
+/* $NetBSD: localtime.c,v 1.49 2010/12/16 18:38:07 christos Exp $ */
/*
** This file is in the public domain, so clarified as of
@@ -10,7 +10,7 @@
#if 0
static char elsieid[] = "@(#)localtime.c 8.9";
#else
-__RCSID("$NetBSD: localtime.c,v 1.48 2010/03/23 20:28:58 drochner Exp $");
+__RCSID("$NetBSD: localtime.c,v 1.49 2010/12/16 18:38:07 christos Exp $");
#endif
#endif /* LIBC_SCCS and not lint */
@@ -28,7 +28,14 @@
#include "reentrant.h"
#if defined(__weak_alias)
+__weak_alias(ctime_r,_ctime_r)
+__weak_alias(ctime_rz,_ctime_rz)
__weak_alias(daylight,_daylight)
+__weak_alias(mktime_z,_mktime_z)
+__weak_alias(localtime_r,_localtime_r)
+__weak_alias(localtime_rz,_localtime_rz)
+__weak_alias(posix2time,_posix2time)
+__weak_alias(posix2time_z,_posix2time_z)
__weak_alias(tzname,_tzname)
#endif
@@ -83,7 +90,7 @@
static const char wildabbr[] = WILDABBR;
-static const char gmt[] = "GMT";
+static char gmt[] = "GMT";
/*
** The DST rules to use if TZ has no rules and we can't load TZDEFRULES.
@@ -118,7 +125,7 @@
#define MY_TZNAME_MAX 255
#endif /* !defined TZNAME_MAX */
-struct state {
+struct __state {
int leapcnt;
int timecnt;
int typecnt;
@@ -145,6 +152,9 @@
#define DAY_OF_YEAR 1 /* n - day of year */
#define MONTH_NTH_DAY_OF_WEEK 2 /* Mm.n.d - month, week, day of week */
+typedef struct tm *(*subfun_t)(const timezone_t sp, const time_t *timep,
+ long offset, struct tm *tmp);
+
/*
** Prototypes for static functions.
*/
@@ -159,11 +169,11 @@
static const char * getsecs(const char * strp, long * secsp);
static const char * getoffset(const char * strp, long * offsetp);
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 void gmtload(timezone_t sp);
+static struct tm * gmtsub(const timezone_t sp, const time_t *timep,
+ long offset, struct tm * tmp);
+static struct tm * localsub(const timezone_t sp, 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);
@@ -172,44 +182,31 @@
static int normalize_overflow(int * tensptr, int * unitsptr,
int base);
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 time_t time1(const timezone_t sp, struct tm * const tmp,
+ subfun_t funcp, long offset);
+static time_t time2(const timezone_t sp, struct tm * const tmp,
+ subfun_t funcp,
+ const long offset, int *const okayp);
+static time_t time2sub(const timezone_t sp, struct tm * consttmp,
+ subfun_t funcp, const long offset,
+ int *const okayp, const int do_norm_secs);
+static struct tm * timesub(const timezone_t sp, const time_t * timep,
+ long offset, struct tm * tmp);
static int tmcomp(const struct tm * atmp,
const struct tm * btmp);
static time_t transtime(time_t janfirst, int year,
const struct rule * rulep, long offset);
-static int typesequiv(const struct state * sp, int a, int b);
-static int tzload(const char * name, struct state * sp,
+static int typesequiv(const timezone_t sp, int a, int b);
+static int tzload(timezone_t sp, const char * name,
int doextend);
-static int tzparse(const char * name, struct state * sp,
+static int tzparse(timezone_t sp, const char * name,
int lastditch);
static void tzset_unlocked(void);
static void tzsetwall_unlocked(void);
-static long leapcorr(time_t * timep);
+static long leapcorr(const timezone_t sp, time_t * timep);
-#ifdef ALL_STATE
-static struct state * lclptr;
-static struct state * gmtptr;
-#endif /* defined ALL_STATE */
-
-#ifndef ALL_STATE
-static struct state lclmem;
-static struct state gmtmem;
-#define lclptr (&lclmem)
-#define gmtptr (&gmtmem)
-#endif /* State Farm */
+static timezone_t lclptr;
+static timezone_t gmtptr;
#ifndef TZ_STRLEN_MAX
#define TZ_STRLEN_MAX 255
@@ -261,11 +258,10 @@
#endif /* defined ALTZONE */
static long
-detzcode(codep)
-const char * const codep;
+detzcode(const char *const codep)
{
- register long result;
- register int i;
+ long result;
+ int i;
result = (codep[0] & 0x80) ? ~0L : 0;
for (i = 0; i < 4; ++i)
@@ -274,11 +270,10 @@
}
static time_t
-detzcode64(codep)
-const char * const codep;
+detzcode64(const char *const codep)
{
- register time_t result;
- register int i;
+ time_t result;
+ int i;
result = (codep[0] & 0x80) ? -1 : 0;
for (i = 0; i < 8; ++i)
@@ -286,11 +281,49 @@
return result;
}
+const char *
+tzgetname(const timezone_t sp, int isdst)
+{
+ int i;
+ for (i = 0; i < sp->timecnt; ++i) {
+ const struct ttinfo *const ttisp = &sp->ttis[sp->types[i]];
+
+ if (ttisp->tt_isdst == isdst)
+ return &sp->chars[ttisp->tt_abbrind];
+ }
+ return NULL;
+}
+
+static void
+settzname_z(timezone_t sp)
+{
+ int i;
+
+ /*
+ ** Scrub the abbreviations.
+ ** First, replace bogus characters.
+ */
+ for (i = 0; i < sp->charcnt; ++i)
+ if (strchr(TZ_ABBR_CHAR_SET, sp->chars[i]) == NULL)
+ sp->chars[i] = TZ_ABBR_ERR_CHAR;
+ /*
+ ** Second, truncate long abbreviations.
+ */
+ for (i = 0; i < sp->typecnt; ++i) {
+ const struct ttinfo * const ttisp = &sp->ttis[i];
+ char * cp = &sp->chars[ttisp->tt_abbrind];
+
+ if (strlen(cp) > TZ_ABBR_MAX_LEN &&
+ strcmp(cp, GRANDPARENTED) != 0)
+ *(cp + TZ_ABBR_MAX_LEN) = '\0';
+ }
+}
+
static void
settzname(void)
{
- register struct state * const sp = lclptr;
- register int i;
+ timezone_t const sp = lclptr;
+ int i;
tzname[0] = (__aconst char *)__UNCONST(wildabbr);
tzname[1] = (__aconst char *)__UNCONST(wildabbr);
@@ -301,14 +334,12 @@
#ifdef ALTZONE
altzone = 0;
#endif /* defined ALTZONE */
-#ifdef ALL_STATE
if (sp == NULL) {
tzname[0] = tzname[1] = (__aconst char *)__UNCONST(gmt);
return;
}
-#endif /* defined ALL_STATE */
for (i = 0; i < sp->typecnt; ++i) {
- register const struct ttinfo * const ttisp = &sp->ttis[i];
+ const struct ttinfo * const ttisp = &sp->ttis[i];
tzname[ttisp->tt_isdst] =
&sp->chars[ttisp->tt_abbrind];
@@ -334,30 +365,11 @@
tzname[ttisp->tt_isdst] =
&sp->chars[ttisp->tt_abbrind];
}
- /*
- ** Finally, scrub the abbreviations.
- ** First, replace bogus characters.
- */
- for (i = 0; i < sp->charcnt; ++i)
- if (strchr(TZ_ABBR_CHAR_SET, sp->chars[i]) == NULL)
- sp->chars[i] = TZ_ABBR_ERR_CHAR;
- /*
- ** Second, truncate long abbreviations.
- */
- for (i = 0; i < sp->typecnt; ++i) {
- register const struct ttinfo * const ttisp = &sp->ttis[i];
- register char * cp = &sp->chars[ttisp->tt_abbrind];
-
- if (strlen(cp) > TZ_ABBR_MAX_LEN &&
- strcmp(cp, GRANDPARENTED) != 0)
- *(cp + TZ_ABBR_MAX_LEN) = '\0';
- }
+ settzname_z(sp);
}
static int
-differ_by_repeat(t1, t0)
-const time_t t1;
-const time_t t0;
+differ_by_repeat(const time_t t1, const time_t t0)
{
/* CONSTCOND */
if (TYPE_INTEGRAL(time_t) &&
@@ -367,16 +379,13 @@
}
static int
-tzload(name, sp, doextend)
-register const char * name;
-register struct state * const sp;
-register const int doextend;
-{
- register const char * p;
- register int i;
- register int fid;
- register int stored;
- register int nread;
+tzload(timezone_t sp, const char *name, const int doextend)
+{
+ const char * p;
+ int i;
+ int fid;
+ int stored;
+ int nread;
union {
struct tzhead tzhead;
char buf[2 * sizeof(struct tzhead) +
@@ -388,7 +397,7 @@
if (name == NULL && (name = TZDEFAULT) == NULL)
return -1;
{
- register int doaccess;
+ int doaccess;
/*
** Section 4.9.1 of the C standard says that
** "FILENAME_MAX expands to an integral constant expression
@@ -468,7 +477,7 @@
return -1;
}
for (i = 0; i < sp->typecnt; ++i) {
- register struct ttinfo * ttisp;
+ struct ttinfo * ttisp;
ttisp = &sp->ttis[i];
ttisp->tt_gmtoff = detzcode(p);
@@ -485,7 +494,7 @@
sp->chars[i] = *p++;
sp->chars[i] = '\0'; /* ensure '\0' at end */
for (i = 0; i < sp->leapcnt; ++i) {
- register struct lsinfo * lsisp;
+ struct lsinfo * lsisp;
lsisp = &sp->lsis[i];
lsisp->ls_trans = (stored == 4) ?
@@ -495,7 +504,7 @@
p += 4;
}
for (i = 0; i < sp->typecnt; ++i) {
- register struct ttinfo * ttisp;
+ struct ttinfo * ttisp;
ttisp = &sp->ttis[i];
if (ttisstdcnt == 0)
@@ -508,7 +517,7 @@
}
}
for (i = 0; i < sp->typecnt; ++i) {
- register struct ttinfo * ttisp;
+ struct ttinfo * ttisp;
ttisp = &sp->ttis[i];
if (ttisgmtcnt == 0)
@@ -538,7 +547,7 @@
/*
** Ignore the beginning (harder).
*/
- register int j;
+ int j;
for (j = 0; j + i < sp->timecnt; ++j) {
sp->ats[j] = sp->ats[j + i];
@@ -567,11 +576,11 @@
if (doextend && nread > 2 &&
u.buf[0] == '\n' && u.buf[nread - 1] == '\n' &&
sp->typecnt + 2 <= TZ_MAX_TYPES) {
- struct state ts;
- register int result;
+ struct __state ts;
+ int result;
u.buf[nread - 1] = '\0';
- result = tzparse(&u.buf[1], &ts, FALSE);
+ result = tzparse(&ts, &u.buf[1], FALSE);
if (result == 0 && ts.typecnt == 2 &&
sp->charcnt + ts.charcnt <= TZ_MAX_CHARS) {
for (i = 0; i < 2; ++i)
@@ -619,20 +628,17 @@
}
static int
-typesequiv(sp, a, b)
-const struct state * const sp;
-const int a;
-const int b;
+typesequiv(const timezone_t sp, const int a, const int b)
{
- register int result;
+ int result;
if (sp == NULL ||
a < 0 || a >= sp->typecnt ||
b < 0 || b >= sp->typecnt)
result = FALSE;
else {
- register const struct ttinfo * ap = &sp->ttis[a];
- register const struct ttinfo * bp = &sp->ttis[b];
+ const struct ttinfo * ap = &sp->ttis[a];
+ const struct ttinfo * bp = &sp->ttis[b];
result = ap->tt_gmtoff == bp->tt_gmtoff &&
ap->tt_isdst == bp->tt_isdst &&
ap->tt_ttisstd == bp->tt_ttisstd &&
@@ -660,9 +666,9 @@
static const char *
getzname(strp)
-register const char * strp;
+const char * strp;
{
- register char c;
+ char c;
while ((c = *strp) != '\0' && !is_digit(c) && c != ',' && c != '-' &&
c != '+')
@@ -680,9 +686,9 @@
*/
static const char *
-getqzname(register const char *strp, const int delim)
+getqzname(const char *strp, const int delim)
{
- register int c;
+ int c;
while ((c = *strp) != '\0' && c != delim)
++strp;
@@ -698,13 +704,13 @@
static const char *
getnum(strp, nump, min, max)
-register const char * strp;
+const char * strp;
int * const nump;
const int min;
const int max;
{
- register char c;
- register int num;
+ char c;
+ int num;
if (strp == NULL || !is_digit(c = *strp)) {
errno = EINVAL;
@@ -736,9 +742,7 @@
*/
static const char *
-getsecs(strp, secsp)
-register const char * strp;
-long * const secsp;
+getsecs(const char *strp, long *const secsp)
{
int num;
@@ -778,11 +782,9 @@
*/
static const char *
-getoffset(strp, offsetp)
-register const char * strp;
-long * const offsetp;
+getoffset(const char *strp, long *const offsetp)
{
- register int neg = 0;
+ int neg = 0;
if (*strp == '-') {
neg = 1;
@@ -805,9 +807,7 @@
*/
static const char *
-getrule(strp, rulep)
-const char * strp;
-register struct rule * const rulep;
+getrule(const char *strp, struct rule *const rulep)
{
if (*strp == 'J') {
/*
@@ -859,15 +859,12 @@
*/
static time_t
-transtime(janfirst, year, rulep, offset)
-const time_t janfirst;
-const int year;
-register const struct rule * const rulep;
-const long offset;
-{
- register int leapyear;
- register time_t value;
- register int i;
+transtime(const time_t janfirst, const int year, const struct rule *const rulep,
+ const long offset)
+{
+ int leapyear;
+ time_t value;
+ int i;
int d, m1, yy0, yy1, yy2, dow;
INITIALIZE(value);
@@ -954,10 +951,7 @@
*/
static int
-tzparse(name, sp, lastditch)
-const char * name;
-register struct state * const sp;
-const int lastditch;
+tzparse(timezone_t sp, const char *name, const int lastditch)
{
const char * stdname;
const char * dstname;
@@ -965,10 +959,10 @@
size_t dstlen;
long stdoffset;
long dstoffset;
- register time_t * atp;
- register unsigned char * typep;
- register char * cp;
- register int load_result;
+ time_t * atp;
+ unsigned char * typep;
+ char * cp;
+ int load_result;
INITIALIZE(dstname);
stdname = name;
@@ -997,7 +991,7 @@
if (name == NULL)
return -1;
}
- load_result = tzload(TZDEFRULES, sp, FALSE);
+ load_result = tzload(sp, TZDEFRULES, FALSE);
if (load_result != 0)
sp->leapcnt = 0; /* so, we're off a little */
if (*name != '\0') {
@@ -1023,8 +1017,8 @@
if (*name == ',' || *name == ';') {
struct rule start;
struct rule end;
- register int year;
- register time_t janfirst;
+ int year;
+ time_t janfirst;
time_t starttime;
time_t endtime;
@@ -1080,12 +1074,12 @@
janfirst = newfirst;
}
} else {
- register long theirstdoffset;
- register long theirdstoffset;
- register long theiroffset;
- register int isdst;
- register int i;
- register int j;
+ long theirstdoffset;
+ long theirdstoffset;
+ long theiroffset;
+ int isdst;
+ int i;
+ int j;
if (*name != '\0')
return -1;
@@ -1189,11 +1183,30 @@
}
static void
-gmtload(sp)
-struct state * const sp;
+gmtload(timezone_t sp)
+{
+ if (tzload(sp, gmt, TRUE) != 0)
+ (void) tzparse(sp, gmt, TRUE);
+}
+
+timezone_t
+tzalloc(const char *name)
+{
+ timezone_t sp = calloc(1, sizeof *sp);
+ if (sp == NULL)
+ return NULL;
+ if (tzload(sp, name, TRUE) != 0) {
+ free(sp);
+ return NULL;
+ }
+ settzname_z(sp);
+ return sp;
+}
+
+void
+tzfree(const timezone_t sp)
{
- if (tzload(gmt, sp, TRUE) != 0)
- (void) tzparse(gmt, sp, TRUE);
+ free(sp);
}
static void
@@ -1203,7 +1216,6 @@
return;
lcl_is_set = -1;
-#ifdef ALL_STATE
if (lclptr == NULL) {
int saveerrno = errno;
lclptr = calloc(1, sizeof *lclptr);
@@ -1213,8 +1225,7 @@
return;
}
}
-#endif /* defined ALL_STATE */
- if (tzload((char *) NULL, lclptr, TRUE) != 0)
+ if (tzload(lclptr, NULL, TRUE) != 0)
gmtload(lclptr);
settzname();
}
@@ -1244,7 +1255,7 @@
void
tzset_unlocked(void)
{
- register const char * name;
+ const char * name;
int saveerrno;
saveerrno = errno;
@@ -1261,7 +1272,6 @@
if (lcl_is_set)
(void)strlcpy(lcl_TZname, name, sizeof(lcl_TZname));
-#ifdef ALL_STATE
if (lclptr == NULL) {
saveerrno = errno;
lclptr = calloc(1, sizeof *lclptr);
@@ -1271,7 +1281,6 @@
return;
}
}
-#endif /* defined ALL_STATE */
if (*name == '\0') {
/*
** User wants it fast rather than right.
@@ -1283,8 +1292,8 @@
lclptr->ttis[0].tt_gmtoff = 0;
lclptr->ttis[0].tt_abbrind = 0;
(void) strlcpy(lclptr->chars, gmt, sizeof(lclptr->chars));
- } else if (tzload(name, lclptr, TRUE) != 0)
- if (name[0] == ':' || tzparse(name, lclptr, FALSE) != 0)
+ } else if (tzload(lclptr, name, TRUE) != 0)
+ if (name[0] == ':' || tzparse(lclptr, name, FALSE) != 0)
(void) gmtload(lclptr);
settzname();
}
@@ -1308,28 +1317,20 @@
/*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;
+localsub(const timezone_t sp, const time_t * const timep, const long offset,
+ struct tm *const tmp)
+{
+ const struct ttinfo * ttisp;
+ int i;
+ 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])) {
time_t newt = t;
- register time_t seconds;
- register time_t tcycles;
- register int_fast64_t icycles;
+ time_t seconds;
+ time_t tcycles;
+ int_fast64_t icycles;
if (t < sp->ats[0])
seconds = sp->ats[0] - t;
@@ -1351,9 +1352,9 @@
errno = EOVERFLOW;
return NULL; /* "cannot happen" */
}
- result = localsub(&newt, offset, tmp);
+ result = localsub(sp, &newt, offset, tmp);
if (result == tmp) {
- register time_t newy;
+ time_t newy;
newy = tmp->tm_year;
if (t < sp->ats[0])
@@ -1375,11 +1376,11 @@
break;
}
} else {
- register int lo = 1;
- register int hi = sp->timecnt;
+ int lo = 1;
+ int hi = sp->timecnt;
while (lo < hi) {
- register int mid = (lo + hi) / 2;
+ int mid = (lo + hi) / 2;
if (t < sp->ats[mid])
hi = mid;
@@ -1394,7 +1395,7 @@
** t += ttisp->tt_gmtoff;
** timesub(&t, 0L, sp, tmp);
*/
- result = timesub(&t, ttisp->tt_gmtoff, sp, tmp);
+ result = timesub(sp, &t, ttisp->tt_gmtoff, tmp);
tmp->tm_isdst = ttisp->tt_isdst;
tzname[tmp->tm_isdst] = &sp->chars[ttisp->tt_abbrind];
#ifdef TM_ZONE
@@ -1403,35 +1404,34 @@
return result;
}
-struct tm *
-localtime(timep)
-const time_t * const timep;
-{
- struct tm *result;
-
- rwlock_wrlock(&lcl_lock);
- tzset_unlocked();
- result = localsub(timep, 0L, &tm);
- rwlock_unlock(&lcl_lock);
- return result;
-}
-
/*
** Re-entrant version of localtime.
*/
struct tm *
-localtime_r(timep, tmp)
-const time_t * const timep;
-struct tm * tmp;
+localtime_r(const time_t * __restrict timep, struct tm *tmp)
{
- struct tm *result;
-
+ rwlock_rdlock(&lcl_lock);
rwlock_rdlock(&lcl_lock);
tzset_unlocked();
- result = localsub(timep, 0L, tmp);
+ tmp = localtime_rz(lclptr, timep, tmp);
rwlock_unlock(&lcl_lock);
- return result;
+ return tmp;
+}
+
+struct tm *
+localtime(const time_t *const timep)
+{
+ return localtime_r(timep, &tm);
+}
+
+struct tm *
+localtime_rz(const timezone_t sp, const time_t * __restrict timep, struct tm *tmp)
+{
+ if (sp == NULL)
+ return gmtsub(NULL, timep, 0L, tmp);
+ else
+ return localsub(sp, timep, 0L, tmp);
}
/*
@@ -1439,32 +1439,26 @@
*/
static struct tm *
-gmtsub(timep, offset, tmp)
-const time_t * const timep;
-const long offset;
-struct tm * const tmp;
+gmtsub(const timezone_t sp, const time_t * const timep, const long offset,
+ struct tm *const tmp)
{
- register struct tm * result;
+ struct tm * result;
#ifdef _REENTRANT
static mutex_t gmt_mutex = MUTEX_INITIALIZER;
#endif
mutex_lock(&gmt_mutex);
if (!gmt_is_set) {
-#ifdef ALL_STATE
int saveerrno;
-#endif
gmt_is_set = TRUE;
-#ifdef ALL_STATE
saveerrno = errno;
gmtptr = calloc(1, sizeof *gmtptr);
errno = saveerrno;
if (gmtptr != NULL)
-#endif /* defined ALL_STATE */
gmtload(gmtptr);
}
mutex_unlock(&gmt_mutex);
- result = timesub(timep, offset, gmtptr, tmp);
+ result = timesub(gmtptr, timep, offset, tmp);
#ifdef TM_ZONE
/*
** Could get fancy here and deliver something such as
@@ -1474,24 +1468,18 @@
if (offset != 0)
tmp->TM_ZONE = (__aconst char *)__UNCONST(wildabbr);
else {
-#ifdef ALL_STATE
if (gmtptr == NULL)
tmp->TM_ZONE = (__aconst char *)__UNCONST(gmt);
else tmp->TM_ZONE = gmtptr->chars;
-#endif /* defined ALL_STATE */
-#ifndef ALL_STATE
- tmp->TM_ZONE = gmtptr->chars;
-#endif /* State Farm */
}
#endif /* defined TM_ZONE */
return result;
}
struct tm *
-gmtime(timep)
-const time_t * const timep;
+gmtime(const time_t *const timep)
{
- return gmtsub(timep, 0L, &tm);
+ return gmtsub(NULL, timep, 0L, &tm);
}
/*
@@ -1499,21 +1487,23 @@
*/
struct tm *
-gmtime_r(timep, tmp)
-const time_t * const timep;
-struct tm * tmp;
+gmtime_r(const time_t * const timep, struct tm *tmp)
{
- return gmtsub(timep, 0L, tmp);
+ return gmtsub(NULL, timep, 0L, tmp);
}
#ifdef STD_INSPIRED
struct tm *
-offtime(timep, offset)
-const time_t * const timep;
-const long offset;
+offtime(const time_t *const timep, long offset)
{
- return gmtsub(timep, offset, &tm);
+ return gmtsub(NULL, timep, offset, &tm);
+}
+
+struct tm *
+offtime_r(const time_t *timep, long offset, struct tm *tmp)
+{
+ return gmtsub(NULL, timep, offset, tmp);
}
#endif /* defined STD_INSPIRED */
@@ -1524,38 +1514,29 @@
*/
static int
-leaps_thru_end_of(y)
-register const int y;
+leaps_thru_end_of(const int y)
{
return (y >= 0) ? (y / 4 - y / 100 + y / 400) :
-(leaps_thru_end_of(-(y + 1)) + 1);
}
static struct tm *
-timesub(timep, offset, sp, tmp)
-const time_t * const timep;
-const long offset;
-register const struct state * const sp;
-register struct tm * const tmp;
-{
- register const struct lsinfo * lp;
- register time_t tdays;
- register int idays; /* unsigned would be so 2003 */
- register long rem;
- int y;
- register const int * ip;
- register long corr;
- register int hit;
- register int i;
+timesub(const timezone_t sp, const time_t *const timep, const long offset,
+ struct tm *const tmp)
+{
+ const struct lsinfo * lp;
+ time_t tdays;
+ int idays; /* unsigned would be so 2003 */
+ long rem;
+ int y;
+ const int * ip;
+ long corr;
+ int hit;
+ int i;
corr = 0;
hit = 0;
-#ifdef ALL_STATE
i = (sp == NULL) ? 0 : sp->leapcnt;
-#endif /* defined ALL_STATE */
-#ifndef ALL_STATE
- i = sp->leapcnt;
-#endif /* State Farm */
while (--i >= 0) {
lp = &sp->lsis[i];
if (*timep >= lp->ls_trans) {
@@ -1581,9 +1562,9 @@
rem = (long) (*timep - tdays * SECSPERDAY);
while (tdays < 0 || tdays >= year_lengths[isleap(y)]) {
int newy;
- register time_t tdelta;
- register int idelta;
- register int leapdays;
+ time_t tdelta;
+ int idelta;
+ int leapdays;
tdelta = tdays / DAYSPERLYEAR;
idelta = (int) tdelta;
@@ -1605,7 +1586,7 @@
y = newy;
}
{
- register long seconds;
+ long seconds;
seconds = tdays * SECSPERDAY + 0.5;
tdays = seconds / SECSPERDAY;
@@ -1676,8 +1657,7 @@
}
char *
-ctime(timep)
-const time_t * const timep;
+ctime(const time_t *const timep)
{
/*
** Section 4.12.3.2 of X3.159-1989 requires that
@@ -1692,9 +1672,7 @@
}
char *
-ctime_r(timep, buf)
-const time_t * const timep;
-char * buf;
+ctime_r(const time_t *const timep, char *buf)
{
struct tm mytm, *rtm;
@@ -1704,6 +1682,17 @@
return asctime_r(rtm, buf);
}
+char *
+ctime_rz(const timezone_t sp, const time_t * timep, char *buf)
+{
+ struct tm mytm, *rtm;
+
+ rtm = localtime_rz(sp, timep, &mytm);
+ if (rtm == NULL)
+ return NULL;
+ return asctime_r(rtm, buf);
+}
+
/*
** Adapted from code provided by Robert Elz, who writes:
** The "best" way to do mktime I think is based on an idea of Bob
@@ -1722,9 +1711,7 @@
*/
static int
-increment_overflow(number, delta)
-int * number;
-int delta;
+increment_overflow(int *number, int delta)
{
int number0;
@@ -1734,9 +1721,7 @@
}
static int
-long_increment_overflow(number, delta)
-long * number;
-int delta;
+long_increment_overflow(long *number, int delta)
{
long number0;
@@ -1746,12 +1731,9 @@
}
static int
-normalize_overflow(tensptr, unitsptr, base)
-int * const tensptr;
-int * const unitsptr;
-const int base;
+normalize_overflow(int *const tensptr, int *const unitsptr, const int base)
{
- register int tensdelta;
+ int tensdelta;
tensdelta = (*unitsptr >= 0) ?
(*unitsptr / base) :
@@ -1761,12 +1743,10 @@
}
static int
-long_normalize_overflow(tensptr, unitsptr, base)
-long * const tensptr;
-int * const unitsptr;
-const int base;
+long_normalize_overflow(long *const tensptr, int *const unitsptr,
+ const int base)
{
- register int tensdelta;
+ int tensdelta;
tensdelta = (*unitsptr >= 0) ?
(*unitsptr / base) :
@@ -1776,11 +1756,9 @@
}
static int
-tmcomp(atmp, btmp)
-register const struct tm * const atmp;
-register const struct tm * const btmp;
+tmcomp(const struct tm *const atmp, const struct tm *const btmp)
{
- register int result;
+ int result;
if ((result = (atmp->tm_year - btmp->tm_year)) == 0 &&
(result = (atmp->tm_mon - btmp->tm_mon)) == 0 &&
@@ -1792,20 +1770,15 @@
}
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;
- register long li;
- register time_t lo;
- register time_t hi;
+time2sub(const timezone_t sp, struct tm *const tmp, subfun_t funcp,
+ const long offset, int *const okayp, const int do_norm_secs)
+{
+ int dir;
+ int i, j;
+ int saved_seconds;
+ long li;
+ time_t lo;
+ time_t hi;
long y;
time_t newt;
time_t t;
@@ -1906,7 +1879,7 @@
t = lo;
else if (t > hi)
t = hi;
- if ((*funcp)(&t, offset, &mytm) == NULL) {
+ if ((*funcp)(sp, &t, offset, &mytm) == NULL) {
/*
** Assume that t is too extreme to be represented in
** a struct tm; arrange things so that it is less
@@ -1941,12 +1914,8 @@
** 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;
-#endif /* defined ALL_STATE */
for (i = sp->typecnt - 1; i >= 0; --i) {
if (sp->ttis[i].tt_isdst != yourtm.tm_isdst)
continue;
@@ -1955,7 +1924,7 @@
continue;
newt = t + sp->ttis[j].tt_gmtoff -
sp->ttis[i].tt_gmtoff;
- if ((*funcp)(&newt, offset, &mytm) == NULL)
+ if ((*funcp)(sp, &newt, offset, &mytm) == NULL)
continue;
if (tmcomp(&mytm, &yourtm) != 0)
continue;
@@ -1975,17 +1944,14 @@
if ((newt < t) != (saved_seconds < 0))
return WRONG;
t = newt;
- if ((*funcp)(&t, offset, tmp))
+ if ((*funcp)(sp, &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;
+time2(const timezone_t sp, struct tm *const tmp, subfun_t funcp,
+ const long offset, int *const okayp)
{
time_t t;
@@ -1994,29 +1960,26 @@
** (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);
+ t = time2sub(sp, tmp, funcp, offset, okayp, FALSE);
+ return *okayp ? t : time2sub(sp, 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;
- register int nseen;
+time1(const timezone_t sp, struct tm *const tmp, subfun_t funcp,
+ long offset)
+{
+ time_t t;
+ int samei, otheri;
+ int sameind, otherind;
+ int i;
+ int nseen;
int seen[TZ_MAX_TYPES];
int types[TZ_MAX_TYPES];
int okay;
if (tmp->tm_isdst > 1)
tmp->tm_isdst = 1;
- t = time2(tmp, funcp, offset, &okay);
+ t = time2(sp, tmp, funcp, offset, &okay);
#ifdef PCTS
/*
** PCTS code courtesy Grant Sullivan.
@@ -2036,11 +1999,8 @@
** 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;
-#endif /* defined ALL_STATE */
for (i = 0; i < sp->typecnt; ++i)
seen[i] = FALSE;
nseen = 0;
@@ -2060,7 +2020,7 @@
tmp->tm_sec += (int)(sp->ttis[otheri].tt_gmtoff -
sp->ttis[samei].tt_gmtoff);
tmp->tm_isdst = !tmp->tm_isdst;
- t = time2(tmp, funcp, offset, &okay);
+ t = time2(sp, tmp, funcp, offset, &okay);
if (okay)
return t;
tmp->tm_sec -= (int)(sp->ttis[otheri].tt_gmtoff -
@@ -2072,43 +2032,55 @@
}
time_t
-mktime(tmp)
-struct tm * const tmp;
+mktime_z(const timezone_t sp, struct tm *tmp)
+{
+ if (sp == NULL)
+ return time1(NULL, tmp, gmtsub, 0L);
+ else
+ return time1(sp, tmp, localsub, 0L);
+}
+
+time_t
+mktime(struct tm * const tmp)
{
time_t result;
rwlock_wrlock(&lcl_lock);
tzset_unlocked();
- result = time1(tmp, localsub, 0L);
+ result = mktime_z(lclptr, tmp);
rwlock_unlock(&lcl_lock);
- return (result);
+ return result;
}
#ifdef STD_INSPIRED
time_t
-timelocal(tmp)
-struct tm * const tmp;
+timelocal_z(const timezone_t sp, struct tm *tmp)
+{
+ if (tmp != NULL)
+ tmp->tm_isdst = -1; /* in case it wasn't initialized */
+ return mktime_z(sp, tmp);
+}
+
+time_t
+timelocal(struct tm *const tmp)
{
tmp->tm_isdst = -1; /* in case it wasn't initialized */
return mktime(tmp);
}
time_t
-timegm(tmp)
-struct tm * const tmp;
+timegm(struct tm *const tmp)
{
tmp->tm_isdst = 0;
- return time1(tmp, gmtsub, 0L);
+ return time1(gmtptr, tmp, gmtsub, 0L);
}
time_t
-timeoff(tmp, offset)
-struct tm * const tmp;
-const long offset;
+timeoff(struct tm *const tmp, const long offset)
{
tmp->tm_isdst = 0;
- return time1(tmp, gmtsub, offset);
+ return time1(gmtptr, tmp, gmtsub, offset);
}
#endif /* defined STD_INSPIRED */
@@ -2121,10 +2093,9 @@
*/
long
-gtime(tmp)
-struct tm * const tmp;
+gtime(struct tm *const tmp)
{
- const time_t t = mktime(tmp);
+ const time_t t = mktime(tmp);
if (t == WRONG)
return -1;
@@ -2148,14 +2119,11 @@
*/
static long
-leapcorr(timep)
-time_t * timep;
+leapcorr(const timezone_t sp, time_t *timep)
{
- register struct state * sp;
- register struct lsinfo * lp;
- register int i;
+ struct lsinfo * lp;
+ int i;
- sp = lclptr;
i = sp->leapcnt;
while (--i >= 0) {
lp = &sp->lsis[i];
@@ -2166,56 +2134,68 @@
}
time_t
-time2posix(t)
-time_t t;
+time2posix_z(const timezone_t sp, time_t t)
{
- time_t result;
+ return t - leapcorr(sp, &t);
+}
+time_t
+time2posix(time_t t)
+{
+ time_t result;
rwlock_wrlock(&lcl_lock);
tzset_unlocked();
- result = t - leapcorr(&t);
+ result = t - leapcorr(lclptr, &t);
rwlock_unlock(&lcl_lock);
return (result);
}
time_t
-posix2time(t)
-time_t t;
+posix2time_z(const timezone_t sp, time_t t)
{
time_t x;
time_t y;
- rwlock_wrlock(&lcl_lock);
- tzset_unlocked();
/*
** For a positive leap second hit, the result
** is not unique. For a negative leap second
** hit, the corresponding time doesn't exist,
** so we return an adjacent second.
*/
- x = t + leapcorr(&t);
- y = x - leapcorr(&x);
+ x = t + leapcorr(sp, &t);
+ y = x - leapcorr(sp, &x);
if (y < t) {
do {
x++;
- y = x - leapcorr(&x);
+ y = x - leapcorr(sp, &x);
} while (y < t);
if (t != y) {
- rwlock_unlock(&lcl_lock);
return x - 1;
}
} else if (y > t) {
do {
--x;
- y = x - leapcorr(&x);
+ y = x - leapcorr(sp, &x);
} while (y > t);
if (t != y) {
- rwlock_unlock(&lcl_lock);
return x + 1;
}
}
- rwlock_unlock(&lcl_lock);
return x;
}
+
+
+time_t
+posix2time(time_t t)
+{
+ time_t result;
+
+ rwlock_wrlock(&lcl_lock);
+ tzset_unlocked();
+ result = posix2time_z(lclptr, t);
+ rwlock_unlock(&lcl_lock);
+ return result;
+}
+
#endif /* defined STD_INSPIRED */
Index: src/lib/libc/time/offtime.3
diff -u src/lib/libc/time/offtime.3:1.1 src/lib/libc/time/offtime.3:1.2
--- src/lib/libc/time/offtime.3:1.1 Sun May 9 22:02:00 2004
+++ src/lib/libc/time/offtime.3 Thu Dec 16 13:38:07 2010
@@ -1,7 +1,7 @@
-.\" $NetBSD: offtime.3,v 1.1 2004/05/10 02:02:00 kleink Exp $
+.\" $NetBSD: offtime.3,v 1.2 2010/12/16 18:38:07 christos Exp $
.\" Written by Klaus Klein, May 10, 2004.
.\" Public domain.
-.Dd May 10, 2004
+.Dd December 14, 2010
.Dt OFFTIME 3
.Os
.Sh NAME
@@ -16,6 +16,8 @@
.In time.h
.Ft struct tm *
.Fn offtime "const time_t * clock" "long int offset"
+.Ft struct tm *
+.Fn offtime_r "const time_t * clock" "long int offset" "struct tm *ret"
.Ft time_t
.Fn timeoff "struct tm * tm" "long int offset"
.Ft time_t
@@ -33,6 +35,15 @@
seconds,
into broken-down time, expressed as Coordinated Universal Time (UTC).
.Pp
+.Fn offtime_r
+is similar to
+.Fn offtime
+but it places the returned
+.Ft "struct tm *"
+in the user supplied
+.Fa ret
+argument.
+.Pp
.Fn timeoff
converts the broken-down time
.Fa tm ,
Index: src/lib/libc/time/strftime.3
diff -u src/lib/libc/time/strftime.3:1.26 src/lib/libc/time/strftime.3:1.27
--- src/lib/libc/time/strftime.3:1.26 Sat May 29 16:32:18 2010
+++ src/lib/libc/time/strftime.3 Thu Dec 16 13:38:07 2010
@@ -30,13 +30,14 @@
.\" SUCH DAMAGE.
.\"
.\" from: @(#)strftime.3 5.12 (Berkeley) 6/29/91
-.\" $NetBSD: strftime.3,v 1.26 2010/05/29 20:32:18 dholland Exp $
+.\" $NetBSD: strftime.3,v 1.27 2010/12/16 18:38:07 christos Exp $
.\"
-.Dd May 29, 2010
+.Dd December 14, 2010
.Dt STRFTIME 3
.Os
.Sh NAME
-.Nm strftime
+.Nm strftime ,
+.Nm strftime_z
.Nd format date and time
.Sh LIBRARY
.Lb libc
@@ -44,6 +45,8 @@
.In time.h
.Ft size_t
.Fn strftime "char * restrict buf" "size_t maxsize" "const char * restrict format" "const struct tm * restrict timeptr"
+.Ft size_t
+.Fn strftime_z "const timezone_t tz" "char * restrict buf" "size_t maxsize" "const char * restrict format" "const struct tm * restrict timeptr"
.Sh DESCRIPTION
The
.Fn strftime
@@ -193,6 +196,15 @@
is replaced by
.Ql % .
.El
+.Pp
+The
+.Fn strftime_z
+function is similar to
+.Fn strftime ,
+but it also takes a
+.Ft "const timezone_t"
+.Fa tz
+argument.
.Sh SEE ALSO
.Xr date 1 ,
.Xr printf 1 ,
Index: src/lib/libc/time/strftime.c
diff -u src/lib/libc/time/strftime.c:1.20 src/lib/libc/time/strftime.c:1.21
--- src/lib/libc/time/strftime.c:1.20 Thu Dec 31 17:49:16 2009
+++ src/lib/libc/time/strftime.c Thu Dec 16 13:38:07 2010
@@ -1,4 +1,4 @@
-/* $NetBSD: strftime.c,v 1.20 2009/12/31 22:49:16 mlelstv Exp $ */
+/* $NetBSD: strftime.c,v 1.21 2010/12/16 18:38:07 christos Exp $ */
#include <sys/cdefs.h>
#if defined(LIBC_SCCS) && !defined(lint)
@@ -6,7 +6,7 @@
static char elsieid[] = "@(#)strftime.c 7.64";
static char elsieid[] = "@(#)strftime.c 8.3";
#else
-__RCSID("$NetBSD: strftime.c,v 1.20 2009/12/31 22:49:16 mlelstv Exp $");
+__RCSID("$NetBSD: strftime.c,v 1.21 2010/12/16 18:38:07 christos Exp $");
#endif
#endif /* LIBC_SCCS and not lint */
@@ -73,14 +73,18 @@
#include "fcntl.h"
#include "locale.h"
+#ifdef __weak_alias
+__weak_alias(strftime_z, _strftime_z)
+#endif
+
#include "sys/localedef.h"
#define Locale _CurrentTimeLocale
#define c_fmt d_t_fmt
static char * _add(const char *, char *, const char *);
static char * _conv(int, const char *, char *, const char *);
-static char * _fmt(const char *, const struct tm *, char *, const char *,
- int *);
+static char * _fmt(const timezone_t, const char *, const struct tm *, char *,
+ const char *, int *);
static char * _yconv(int, int, int, int, char *, const char *);
extern char * tzname[];
@@ -95,18 +99,15 @@
#define IN_ALL 3
size_t
-strftime(s, maxsize, format, t)
-char * const s;
-const size_t maxsize;
-const char * const format;
-const struct tm * const t;
+strftime_z(const timezone_t sp, char * const s, const size_t maxsize,
+ const char * const format, const struct tm * const t)
{
char * p;
int warn;
- tzset();
warn = IN_NONE;
- p = _fmt(((format == NULL) ? "%c" : format), t, s, s + maxsize, &warn);
+ p = _fmt(sp, ((format == NULL) ? "%c" : format), t, s, s + maxsize,
+ &warn);
#ifndef NO_RUN_TIME_WARNINGS_ABOUT_YEAR_2000_PROBLEMS_THANK_YOU
if (warn != IN_NONE && getenv(YEAR_2000_NAME) != NULL) {
(void) fprintf(stderr, "\n");
@@ -130,12 +131,8 @@
}
static char *
-_fmt(format, t, pt, ptlim, warnp)
-const char * format;
-const struct tm * const t;
-char * pt;
-const char * const ptlim;
-int * warnp;
+_fmt(const timezone_t sp, const char *format, const struct tm * const t,
+ char *pt, const char *const ptlim, int *warnp)
{
for ( ; *format; ++format) {
if (*format == '%') {
@@ -184,7 +181,7 @@
{
int warn2 = IN_SOME;
- pt = _fmt(Locale->c_fmt, t, pt, ptlim, &warn2);
+ pt = _fmt(sp, Locale->c_fmt, t, pt, ptlim, &warn2);
if (warn2 == IN_ALL)
warn2 = IN_THIS;
if (warn2 > *warnp)
@@ -192,7 +189,7 @@
}
continue;
case 'D':
- pt = _fmt("%m/%d/%y", t, pt, ptlim, warnp);
+ pt = _fmt(sp, "%m/%d/%y", t, pt, ptlim, warnp);
continue;
case 'd':
pt = _conv(t->tm_mday, "%02d", pt, ptlim);
@@ -213,7 +210,7 @@
pt = _conv(t->tm_mday, "%2d", pt, ptlim);
continue;
case 'F':
- pt = _fmt("%Y-%m-%d", t, pt, ptlim, warnp);
+ pt = _fmt(sp, "%Y-%m-%d", t, pt, ptlim, warnp);
continue;
case 'H':
pt = _conv(t->tm_hour, "%02d", pt, ptlim);
@@ -277,10 +274,10 @@
pt, ptlim);
continue;
case 'R':
- pt = _fmt("%H:%M", t, pt, ptlim, warnp);
+ pt = _fmt(sp, "%H:%M", t, pt, ptlim, warnp);
continue;
case 'r':
- pt = _fmt(Locale->t_fmt_ampm, t, pt, ptlim,
+ pt = _fmt(sp, Locale->t_fmt_ampm, t, pt, ptlim,
warnp);
continue;
case 'S':
@@ -306,7 +303,7 @@
}
continue;
case 'T':
- pt = _fmt("%H:%M:%S", t, pt, ptlim, warnp);
+ pt = _fmt(sp, "%H:%M:%S", t, pt, ptlim, warnp);
continue;
case 't':
pt = _add("\t", pt, ptlim);
@@ -421,7 +418,7 @@
** "date as dd-bbb-YYYY"
** (ado, 1993-05-24)
*/
- pt = _fmt("%e-%b-%Y", t, pt, ptlim, warnp);
+ pt = _fmt(sp, "%e-%b-%Y", t, pt, ptlim, warnp);
continue;
case 'W':
pt = _conv((t->tm_yday + DAYSPERWEEK -
@@ -434,13 +431,13 @@
pt = _conv(t->tm_wday, "%d", pt, ptlim);
continue;
case 'X':
- pt = _fmt(Locale->t_fmt, t, pt, ptlim, warnp);
+ pt = _fmt(sp, Locale->t_fmt, t, pt, ptlim, warnp);
continue;
case 'x':
{
int warn2 = IN_SOME;
- pt = _fmt(Locale->d_fmt, t, pt, ptlim, &warn2);
+ pt = _fmt(sp, Locale->d_fmt, t, pt, ptlim, &warn2);
if (warn2 == IN_ALL)
warn2 = IN_THIS;
if (warn2 > *warnp)
@@ -463,8 +460,10 @@
else
#endif /* defined TM_ZONE */
if (t->tm_isdst >= 0)
- pt = _add(tzname[t->tm_isdst != 0],
- pt, ptlim);
+ pt = _add((sp ?
+ tzgetname(sp, t->tm_isdst) :
+ tzname[t->tm_isdst != 0]),
+ pt, ptlim);
/*
** C99 says that %Z must be replaced by the
** empty string if the time zone is not
@@ -556,7 +555,7 @@
continue;
#if 0
case '+':
- pt = _fmt(Locale->date_fmt, t, pt, ptlim,
+ pt = _fmt(sp, Locale->date_fmt, t, pt, ptlim,
warnp);
continue;
#endif
@@ -577,6 +576,14 @@
return pt;
}
+size_t
+strftime(char * const s, const size_t maxsize,
+ const char * const format, const struct tm * const t)
+{
+ tzset();
+ return strftime_z(NULL, s, maxsize, format, t);
+}
+
static char *
_conv(n, format, pt, ptlim)
const int n;
Index: src/lib/libc/time/time2posix.3
diff -u src/lib/libc/time/time2posix.3:1.15 src/lib/libc/time/time2posix.3:1.16
--- src/lib/libc/time/time2posix.3:1.15 Thu Dec 31 17:49:16 2009
+++ src/lib/libc/time/time2posix.3 Thu Dec 16 13:38:07 2010
@@ -1,10 +1,12 @@
-.\" $NetBSD: time2posix.3,v 1.15 2009/12/31 22:49:16 mlelstv Exp $
-.Dd April 1, 2001
+.\" $NetBSD: time2posix.3,v 1.16 2010/12/16 18:38:07 christos Exp $
+.Dd December 4, 2010
.Dt TIME2POSIX 3
.Os
.Sh NAME
.Nm time2posix ,
-.Nm posix2time
+.Nm time2posix_z ,
+.Nm posix2time ,
+.Nm posix2time_z ,
.Nd convert seconds since the Epoch
.Sh LIBRARY
.Lb libc
@@ -13,7 +15,11 @@
.Ft time_t
.Fn time2posix "time_t t"
.Ft time_t
+.Fn time2posix_z "const timezone_t tz" "time_t t"
+.Ft time_t
.Fn posix2time "time_t t"
+.Ft time_t
+.Fn posix2time_z "const timezone_t tz" "time_t t"
.Sh DESCRIPTION
.St -p1003.1
legislates that a
@@ -42,7 +48,10 @@
passed-to functions such as
.Xr time 3 ,
.Xr localtime 3 ,
+.Xr localtime_r 3 ,
+.Xr localtime_rz 3 ,
.Xr mktime 3 ,
+.Xr mktime_z 3 ,
and
.Xr difftime 3 .
However, POSIX gives an arithmetic expression for directly computing a
@@ -55,9 +64,11 @@
leap seconds correctly.
.Pp
The
-.Fn time2posix
-and
+.Fn time2posix ,
+.Fn time2posix_z ,
.Fn posix2time
+and
+.Fn posix2time_z
functions are provided to address this
.Va time_t
mismatch by converting between local
@@ -69,19 +80,32 @@
older applications, or when communicating with POSIX-compliant systems.
.Pp
.Fn time2posix
-is single-valued.
+and
+.Fn time2posix_z
+are single-valued.
That is, every local
.Va time_t
corresponds to a single POSIX
.Va time_t .
.Fn posix2time
-is less well-behaved: for a positive leap second hit the result is not
+and
+.Fn posix2time
+are less well-behaved: for a positive leap second hit the result is not
unique, and for a negative leap second hit the corresponding POSIX
.Va time_t
doesn't exist so an adjacent value is returned.
Both of these are good indicators of the inferiority of the POSIX
representation.
.Pp
+The
+.Dq z
+variants of the two functions behave exactly like their counterparts,
+but they operate in the given
+.Fa tz
+argument which was previously allocated using
+.Xr tzalloc 3
+and are re-entrant.
+.Pp
The following table summarizes the relationship between a
.Va time_t
and its conversion to, and back from, the POSIX representation over
@@ -115,7 +139,11 @@
.Sh SEE ALSO
.Xr difftime 3 ,
.Xr localtime 3 ,
+.Xr localtime_r 3 ,
+.Xr localtime_rz 3 ,
+.Xr tzalloc 3 ,
.Xr mktime 3 ,
+.Xr mktime_z 3 ,
.Xr time 3
.\" @(#)time2posix.3 7.7
.\" This file is in the public domain, so clarified as of