Merge "Sync with upstream tzcode (2015g)."
diff --git a/libc/Android.mk b/libc/Android.mk
index bc6bbf3..b7278b7 100644
--- a/libc/Android.mk
+++ b/libc/Android.mk
@@ -688,11 +688,13 @@
 
 LOCAL_CFLAGS := $(libc_common_cflags) \
     -fvisibility=hidden \
+    -Wno-unused-parameter \
 
 # Don't use ridiculous amounts of stack.
 LOCAL_CFLAGS += -DALL_STATE
 # Include tzsetwall, timelocal, timegm, time2posix, and posix2time.
 LOCAL_CFLAGS += -DSTD_INSPIRED
+LOCAL_CFLAGS += -DTHREAD_SAFE
 # The name of the tm_gmtoff field in our struct tm.
 LOCAL_CFLAGS += -DTM_GMTOFF=tm_gmtoff
 # Where we store our tzdata.
diff --git a/libc/tzcode/asctime.c b/libc/tzcode/asctime.c
index fea24e4..337a313 100644
--- a/libc/tzcode/asctime.c
+++ b/libc/tzcode/asctime.c
@@ -55,7 +55,7 @@
 ** ??? ???-2147483648 -2147483648:-2147483648:-2147483648     -2147483648\n
 ** (two three-character abbreviations, five strings denoting integers,
 ** seven explicit spaces, two explicit colons, a newline,
-** and a trailing ASCII nul).
+** and a trailing NUL byte).
 ** The values above are for systems where an int is 32 bits and are provided
 ** as an example; the define below calculates the maximum for the system at
 ** hand.
@@ -99,11 +99,11 @@
 	** Assume that strftime is unaffected by other out-of-range members
 	** (e.g., timeptr->tm_mday) when processing "%Y".
 	*/
-	(void) strftime(year, sizeof year, "%Y", timeptr);
+	strftime(year, sizeof year, "%Y", timeptr);
 	/*
 	** We avoid using snprintf since it's not available on all systems.
 	*/
-	(void) snprintf(result, sizeof(result), /* Android change: use snprintf. */
+	snprintf(result, sizeof(result), /* Android change: use snprintf. */
 		((strlen(year) <= 4) ? ASCTIME_FMT : ASCTIME_FMT_B),
 		wn, mn,
 		timeptr->tm_mday, timeptr->tm_hour,
@@ -112,11 +112,7 @@
 	if (strlen(result) < STD_ASCTIME_BUF_SIZE || buf == buf_asctime)
 		return strcpy(buf, result);
 	else {
-#ifdef EOVERFLOW
 		errno = EOVERFLOW;
-#else /* !defined EOVERFLOW */
-		errno = EINVAL;
-#endif /* !defined EOVERFLOW */
 		return NULL;
 	}
 }
diff --git a/libc/tzcode/difftime.c b/libc/tzcode/difftime.c
index 449cdf0..ba2fd03 100644
--- a/libc/tzcode/difftime.c
+++ b/libc/tzcode/difftime.c
@@ -7,42 +7,52 @@
 
 #include "private.h"	/* for time_t and TYPE_SIGNED */
 
+/* Return -X as a double.  Using this avoids casting to 'double'.  */
+static double
+dminus(double x)
+{
+  return -x;
+}
+
 double ATTRIBUTE_CONST
-difftime(const time_t time1, const time_t time0)
+difftime(time_t time1, time_t time0)
 {
 	/*
-	** If (sizeof (double) > sizeof (time_t)) simply convert and subtract
+	** If double is large enough, simply convert and subtract
 	** (assuming that the larger type has more precision).
 	*/
-	if (sizeof (double) > sizeof (time_t))
-		return (double) time1 - (double) time0;
-	if (!TYPE_SIGNED(time_t)) {
-		/*
-		** The difference of two unsigned values can't overflow
-		** if the minuend is greater than or equal to the subtrahend.
-		*/
-		if (time1 >= time0)
-			return            time1 - time0;
-		else	return -(double) (time0 - time1);
+	if (sizeof (time_t) < sizeof (double)) {
+	  double t1 = time1, t0 = time0;
+	  return t1 - t0;
 	}
+
+	/*
+	** The difference of two unsigned values can't overflow
+	** if the minuend is greater than or equal to the subtrahend.
+	*/
+	if (!TYPE_SIGNED(time_t))
+	  return time0 <= time1 ? time1 - time0 : dminus(time0 - time1);
+
+	/* Use uintmax_t if wide enough.  */
+	if (sizeof (time_t) <= sizeof (uintmax_t)) {
+	  uintmax_t t1 = time1, t0 = time0;
+	  return time0 <= time1 ? t1 - t0 : dminus(t0 - t1);
+	}
+
 	/*
 	** Handle cases where both time1 and time0 have the same sign
 	** (meaning that their difference cannot overflow).
 	*/
 	if ((time1 < 0) == (time0 < 0))
-		return time1 - time0;
+	  return time1 - time0;
+
 	/*
-	** time1 and time0 have opposite signs.
-	** Punt if uintmax_t is too narrow.
+	** The values have opposite signs and uintmax_t is too narrow.
 	** This suffers from double rounding; attempt to lessen that
 	** by using long double temporaries.
 	*/
-	if (sizeof (uintmax_t) < sizeof (time_t))
-		return (long double) time1 - (long double) time0;
-	/*
-	** Stay calm...decent optimizers will eliminate the complexity below.
-	*/
-	if (time1 >= 0 /* && time0 < 0 */)
-		return    (uintmax_t) time1 + (uintmax_t) (-1 - time0) + 1;
-	return -(double) ((uintmax_t) time0 + (uintmax_t) (-1 - time1) + 1);
+	{
+	  long double t1 = time1, t0 = time0;
+	  return t1 - t0;
+	}
 }
diff --git a/libc/tzcode/localtime.c b/libc/tzcode/localtime.c
index 3a8a367..79c4a9a 100644
--- a/libc/tzcode/localtime.c
+++ b/libc/tzcode/localtime.c
@@ -10,10 +10,30 @@
 
 /*LINTLIBRARY*/
 
+#define LOCALTIME_IMPLEMENTATION
 #include "private.h"
+
 #include "tzfile.h"
 #include "fcntl.h"
 
+#if THREAD_SAFE
+# include <pthread.h>
+static pthread_mutex_t locallock = PTHREAD_MUTEX_INITIALIZER;
+static int lock(void) { return pthread_mutex_lock(&locallock); }
+static void unlock(void) { pthread_mutex_unlock(&locallock); }
+#else
+static int lock(void) { return 0; }
+static void unlock(void) { }
+#endif
+
+/* NETBSD_INSPIRED_EXTERN functions are exported to callers if
+   NETBSD_INSPIRED is defined, and are private otherwise.  */
+#if NETBSD_INSPIRED
+# define NETBSD_INSPIRED_EXTERN
+#else
+# define NETBSD_INSPIRED_EXTERN static
+#endif
+
 #ifndef TZ_ABBR_MAX_LEN
 #define TZ_ABBR_MAX_LEN 16
 #endif /* !defined TZ_ABBR_MAX_LEN */
@@ -38,19 +58,6 @@
 #define OPEN_MODE   O_RDONLY
 #endif /* !defined O_BINARY */
 
-#if 0
-#  define  XLOG(xx)  printf xx , fflush(stdout)
-#else
-#  define  XLOG(x)   do{}while (0)
-#endif
-
-/* BEGIN android-added: thread-safety. */
-#include <pthread.h>
-static pthread_mutex_t _tzMutex = PTHREAD_MUTEX_INITIALIZER;
-static inline void _tzLock(void) { pthread_mutex_lock(&_tzMutex); }
-static inline void _tzUnlock(void) { pthread_mutex_unlock(&_tzMutex); }
-/* END android-added */
-
 #ifndef WILDABBR
 /*
 ** Someone might make incorrect use of a time zone abbreviation:
@@ -91,10 +98,10 @@
 
 struct ttinfo {              /* time type information */
     int_fast32_t tt_gmtoff;  /* UT offset in seconds */
-    int          tt_isdst;   /* used to set tm_isdst */
+    bool         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 UT */
+    bool         tt_ttisstd; /* transition is std time */
+    bool         tt_ttisgmt; /* transition is UT */
 };
 
 struct lsinfo {              /* leap second information */
@@ -102,6 +109,7 @@
     int_fast64_t ls_corr;    /* correction to apply */
 };
 
+#define SMALLEST(a, b)	(((a) < (b)) ? (a) : (b))
 #define BIGGEST(a, b)   (((a) > (b)) ? (a) : (b))
 
 #ifdef TZNAME_MAX
@@ -116,8 +124,8 @@
     int           timecnt;
     int           typecnt;
     int           charcnt;
-    int           goback;
-    int           goahead;
+    bool          goback;
+    bool          goahead;
     time_t        ats[TZ_MAX_TIMES];
     unsigned char types[TZ_MAX_TIMES];
     struct ttinfo ttis[TZ_MAX_TYPES];
@@ -127,74 +135,29 @@
     int           defaulttype; /* for early times or if no transitions */
 };
 
+enum r_type {
+  JULIAN_DAY,		/* Jn = Julian day */
+  DAY_OF_YEAR,		/* n = day of year */
+  MONTH_NTH_DAY_OF_WEEK	/* Mm.n.d = month, week, day of week */
+};
+
 struct rule {
-    int          r_type; /* type of rule; see below */
+	enum r_type	r_type;		/* type of rule */
     int          r_day;  /* day number of rule */
     int          r_week; /* week number of rule */
     int          r_mon;  /* month number of rule */
     int_fast32_t r_time; /* transition time of rule */
 };
 
-#define JULIAN_DAY             0       /* Jn = Julian day */
-#define DAY_OF_YEAR            1       /* n = day of year */
-#define MONTH_NTH_DAY_OF_WEEK  2       /* Mm.n.d = month, week, day of week */
-
-/*
-** Prototypes for static functions.
-*/
-
-/* NOTE: all internal functions assume that _tzLock() was already called */
-
-static int __bionic_open_tzdata(const char*, int*);
-static int_fast32_t detzcode(const char * codep);
-static int_fast64_t detzcode64(const char * codep);
-static int      differ_by_repeat(time_t t1, time_t t0);
-static const char * getzname(const char * strp) ATTRIBUTE_PURE;
-static const char * getqzname(const char * strp, const int delim)
-        ATTRIBUTE_PURE;
-static const char * getnum(const char * strp, int * nump, int min,
-                int max);
-static const char * getsecs(const char * strp, int_fast32_t * secsp);
-static const char * getoffset(const char * strp, int_fast32_t * 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, int_fast32_t offset,
-                struct tm * tmp, struct state * sp); // android-changed: added sp.
-static struct tm *  localsub(const time_t * timep, int_fast32_t offset,
-                struct tm * tmp, struct state * sp); // android-changed: added sp.
-static int      increment_overflow(int * number, int delta);
-static int      leaps_thru_end_of(int y) ATTRIBUTE_PURE;
-static int      increment_overflow32(int_fast32_t * number, int delta);
-static int      increment_overflow_time(time_t *t, int_fast32_t delta);
-static int      normalize_overflow32(int_fast32_t * tensptr,
-                int * unitsptr, int base);
-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 *,
-                int_fast32_t, struct tm *, struct state *), // android-changed: added state*.
-                int_fast32_t, struct state * sp); // android-changed: added sp.
-static time_t       time2(struct tm * tmp,
-                struct tm * (*funcp)(const time_t *,
-                int_fast32_t, struct tm*, struct state *), // android-changed: added state*.
-                int_fast32_t offset, int * okayp, struct state * sp); // android-changed: added sp.
-static time_t       time2sub(struct tm *tmp,
-                struct tm * (*funcp) (const time_t *,
-                int_fast32_t, struct tm*, struct state *), // android-changed: added state*.
-                int_fast32_t offset, int * okayp, int do_norm_secs, struct state * sp); // android-change: added sp.
-static struct tm *  timesub(const time_t * timep, int_fast32_t offset,
-                const struct state * sp, struct tm * tmp);
-static int      tmcomp(const struct tm * atmp,
-                const struct tm * btmp);
-static int_fast32_t transtime(int year, const struct rule * rulep,
-                int_fast32_t offset)
-        ATTRIBUTE_PURE;
-static int      typesequiv(const struct state * sp, int a, int b);
-static int      tzload(const char * name, struct state * sp,
-                int doextend);
-static int      tzparse(const char * name, struct state * sp,
-                int lastditch);
+static struct tm *gmtsub(struct state const *, time_t const *, int_fast32_t,
+			 struct tm *);
+static bool increment_overflow(int *, int);
+static bool increment_overflow_time(time_t *, int_fast32_t);
+static bool normalize_overflow32(int_fast32_t *, int *, int);
+static struct tm *timesub(time_t const *, int_fast32_t, struct state const *,
+			  struct tm *);
+static bool typesequiv(struct state const *, int, int);
+static bool tzparse(char const *, struct state *, bool);
 
 #ifdef ALL_STATE
 static struct state * lclptr;
@@ -214,7 +177,6 @@
 
 static char lcl_TZname[TZ_STRLEN_MAX + 1];
 static int  lcl_is_set;
-static int  gmt_is_set;
 
 char * tzname[2] = {
     (char *) wildabbr,
@@ -229,107 +191,150 @@
 ** Thanks to Paul Eggert for noting this.
 */
 
-static struct tm    tmGlobal;
+static struct tm	tm;
 
 #ifdef USG_COMPAT
-long                timezone = 0;
-int                 daylight = 0;
+long			timezone;
+int			daylight;
 #endif /* defined USG_COMPAT */
 
 #ifdef ALTZONE
-long                altzone = 0;
+long			altzone;
 #endif /* defined ALTZONE */
 
+/* Initialize *S to a value based on GMTOFF, ISDST, and ABBRIND.  */
+static void
+init_ttinfo(struct ttinfo *s, int_fast32_t gmtoff, bool isdst, int abbrind)
+{
+  s->tt_gmtoff = gmtoff;
+  s->tt_isdst = isdst;
+  s->tt_abbrind = abbrind;
+  s->tt_ttisstd = false;
+  s->tt_ttisgmt = false;
+}
+
 static int_fast32_t
 detzcode(const char *const codep)
 {
-    register int_fast32_t result;
-    register int          i;
+	register int_fast32_t	result;
+	register int		i;
+	int_fast32_t one = 1;
+	int_fast32_t halfmaxval = one << (32 - 2);
+	int_fast32_t maxval = halfmaxval - 1 + halfmaxval;
+	int_fast32_t minval = -1 - maxval;
 
-    result = (codep[0] & 0x80) ? -1 : 0;
-    for (i = 0; i < 4; ++i)
-        result = (result << 8) | (codep[i] & 0xff);
-    return result;
+	result = codep[0] & 0x7f;
+	for (i = 1; i < 4; ++i)
+		result = (result << 8) | (codep[i] & 0xff);
+
+	if (codep[0] & 0x80) {
+	  /* Do two's-complement negation even on non-two's-complement machines.
+	     If the result would be minval - 1, return minval.  */
+	  result -= !TWOS_COMPLEMENT(int_fast32_t) && result != 0;
+	  result += minval;
+	}
+	return result;
 }
 
 static int_fast64_t
 detzcode64(const char *const codep)
 {
-    register int_fast64_t result;
-    register int          i;
+	register uint_fast64_t result;
+	register int	i;
+	int_fast64_t one = 1;
+	int_fast64_t halfmaxval = one << (64 - 2);
+	int_fast64_t maxval = halfmaxval - 1 + halfmaxval;
+	int_fast64_t minval = -TWOS_COMPLEMENT(int_fast64_t) - maxval;
 
-    result = (codep[0] & 0x80) ? -1 : 0;
-    for (i = 0; i < 8; ++i)
-        result = (result << 8) | (codep[i] & 0xff);
-    return result;
+	result = codep[0] & 0x7f;
+	for (i = 1; i < 8; ++i)
+		result = (result << 8) | (codep[i] & 0xff);
+
+	if (codep[0] & 0x80) {
+	  /* Do two's-complement negation even on non-two's-complement machines.
+	     If the result would be minval - 1, return minval.  */
+	  result -= !TWOS_COMPLEMENT(int_fast64_t) && result != 0;
+	  result += minval;
+	}
+	return result;
+}
+
+static void
+update_tzname_etc(struct state const *sp, struct ttinfo const *ttisp)
+{
+  tzname[ttisp->tt_isdst] = (char *) &sp->chars[ttisp->tt_abbrind];
+#ifdef USG_COMPAT
+  if (!ttisp->tt_isdst)
+    timezone = - ttisp->tt_gmtoff;
+#endif
+#ifdef ALTZONE
+  if (ttisp->tt_isdst)
+    altzone = - ttisp->tt_gmtoff;
+#endif
 }
 
 static void
 settzname(void)
 {
-    register struct state * const sp = lclptr;
-    register int                  i;
+	register struct state * const	sp = lclptr;
+	register int			i;
 
-    tzname[0] = tzname[1] = (char *) wildabbr;
+	tzname[0] = tzname[1] = (char *) wildabbr;
 #ifdef USG_COMPAT
-    daylight = 0;
-    timezone = 0;
+	daylight = 0;
+	timezone = 0;
 #endif /* defined USG_COMPAT */
 #ifdef ALTZONE
-    altzone = 0;
+	altzone = 0;
 #endif /* defined ALTZONE */
-    if (sp == NULL) {
-        tzname[0] = tzname[1] = (char *) gmt;
-        return;
-    }
-    /*
-    ** And to get the latest zone names into tzname. . .
-    */
-    for (i = 0; i < sp->typecnt; ++i) {
-        register const struct ttinfo * const    ttisp = &sp->ttis[i];
-
-        tzname[ttisp->tt_isdst] = &sp->chars[ttisp->tt_abbrind];
-    }
-    for (i = 0; i < sp->timecnt; ++i) {
-        register const struct ttinfo * const    ttisp =
-                            &sp->ttis[
-                                sp->types[i]];
-
-        tzname[ttisp->tt_isdst] =
-            &sp->chars[ttisp->tt_abbrind];
+	if (sp == NULL) {
+		tzname[0] = tzname[1] = (char *) gmt;
+		return;
+	}
+	/*
+	** And to get the latest zone names into tzname. . .
+	*/
+	for (i = 0; i < sp->typecnt; ++i) {
+		register const struct ttinfo * const	ttisp = &sp->ttis[i];
+		update_tzname_etc(sp, ttisp);
+	}
+	for (i = 0; i < sp->timecnt; ++i) {
+		register const struct ttinfo * const	ttisp =
+							&sp->ttis[
+								sp->types[i]];
+		update_tzname_etc(sp, ttisp);
 #ifdef USG_COMPAT
-        if (ttisp->tt_isdst)
-            daylight = 1;
-        if (!ttisp->tt_isdst)
-            timezone = -(ttisp->tt_gmtoff);
+		if (ttisp->tt_isdst)
+			daylight = 1;
 #endif /* defined USG_COMPAT */
-#ifdef ALTZONE
-        if (ttisp->tt_isdst)
-            altzone = -(ttisp->tt_gmtoff);
-#endif /* defined ALTZONE */
-    }
-    /*
-    ** 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';
-    }
+	}
 }
 
-static int
-differ_by_repeat(const time_t t1 __unused, const time_t t0 __unused)
+static void
+scrub_abbrs(struct state *sp)
+{
+	int i;
+	/*
+	** 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';
+	}
+}
+
+static bool
+differ_by_repeat(const time_t t1, const time_t t0)
 {
     if (TYPE_BIT(time_t) - TYPE_SIGNED(time_t) < SECSPERREPEAT_BITS)
         return 0;
@@ -338,318 +343,387 @@
 #endif
 }
 
-static int
-tzload(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;
-    typedef union {
-        struct tzhead tzhead;
-        char          buf[2 * sizeof(struct tzhead) +
-                      2 * sizeof *sp +
-                      4 * TZ_MAX_TIMES];
-    } u_t;
-    union local_storage {
-        /*
-        ** Section 4.9.1 of the C standard says that
-        ** "FILENAME_MAX expands to an integral constant expression
-        ** that is the size 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];
+/* Input buffer for data read from a compiled tz file.  */
+union input_buffer {
+  /* The first part of the buffer, interpreted as a header.  */
+  struct tzhead tzhead;
 
-        /* The main part of the storage for this function.  */
-        struct {
-            u_t u;
-            struct state st;
-        } u;
-    };
-    //register char *fullname;
-    register u_t *up;
-    register union local_storage *lsp;
-#ifdef ALL_STATE
-    lsp = malloc(sizeof *lsp);
-    if (!lsp)
-        return -1;
-#else /* !defined ALL_STATE */
-    union local_storage ls;
-    lsp = &ls;
-#endif /* !defined ALL_STATE */
-    //fullname = lsp->fullname;
-    up = &lsp->u.u;
-
-    sp->goback = sp->goahead = FALSE;
-
-    if (! name) {
-        name = TZDEFAULT;
-        if (! name)
-            goto oops;
-    }
-
-    int toread;
-    fid = __bionic_open_tzdata(name, &toread);
-    if (fid < 0)
-        goto oops;
-
-    nread = read(fid, up->buf, sizeof up->buf);
-    if (close(fid) < 0 || nread <= 0)
-        goto oops;
-    for (stored = 4; stored <= 8; stored *= 2) {
-        int ttisstdcnt;
-        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);
-        p = up->tzhead.tzh_charcnt + sizeof up->tzhead.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 ||
-            sp->charcnt < 0 || sp->charcnt > TZ_MAX_CHARS ||
-            (ttisstdcnt != sp->typecnt && ttisstdcnt != 0) ||
-            (ttisgmtcnt != sp->typecnt && ttisgmtcnt != 0))
-                goto oops;
-        if (nread - (p - up->buf) <
-            sp->timecnt * stored +       /* ats */
-            sp->timecnt +                /* types */
-            sp->typecnt * 6 +            /* ttinfos */
-            sp->charcnt +                /* chars */
-            sp->leapcnt * (stored + 4) + /* lsinfos */
-            ttisstdcnt +                 /* ttisstds */
-            ttisgmtcnt)                  /* ttisgmts */
-                goto oops;
-        timecnt = 0;
-        for (i = 0; i < sp->timecnt; ++i) {
-            int_fast64_t at
-              = stored == 4 ? detzcode(p) : detzcode64(p);
-            sp->types[i] = ((TYPE_SIGNED(time_t)
-                     ? time_t_min <= at
-                     : 0 <= at)
-                    && at <= time_t_max);
-            if (sp->types[i]) {
-                if (i && !timecnt && at != time_t_min) {
-                    /*
-                    ** Keep the earlier record, but tweak
-                    ** it so that it starts with the
-                    ** minimum time_t value.
-                    */
-                    sp->types[i - 1] = 1;
-                    sp->ats[timecnt++] = time_t_min;
-                }
-                sp->ats[timecnt++] = at;
-            }
-            p += stored;
-        }
-        timecnt = 0;
-        for (i = 0; i < sp->timecnt; ++i) {
-            unsigned char typ = *p++;
-            if (sp->typecnt <= typ)
-                goto oops;
-            if (sp->types[i])
-                sp->types[timecnt++] = typ;
-        }
-        sp->timecnt = timecnt;
-        for (i = 0; i < sp->typecnt; ++i) {
-            register struct ttinfo *    ttisp;
-
-            ttisp = &sp->ttis[i];
-            ttisp->tt_gmtoff = detzcode(p);
-            p += 4;
-            ttisp->tt_isdst = (unsigned char) *p++;
-            if (ttisp->tt_isdst != 0 && ttisp->tt_isdst != 1)
-                goto oops;
-            ttisp->tt_abbrind = (unsigned char) *p++;
-            if (ttisp->tt_abbrind < 0 ||
-                ttisp->tt_abbrind > sp->charcnt)
-                    goto oops;
-        }
-        for (i = 0; i < sp->charcnt; ++i)
-            sp->chars[i] = *p++;
-        sp->chars[i] = '\0';    /* ensure '\0' at end */
-        for (i = 0; i < sp->leapcnt; ++i) {
-            register struct lsinfo *    lsisp;
-
-            lsisp = &sp->lsis[i];
-            lsisp->ls_trans = (stored == 4) ?
-                detzcode(p) : detzcode64(p);
-            p += stored;
-            lsisp->ls_corr = detzcode(p);
-            p += 4;
-        }
-        for (i = 0; i < sp->typecnt; ++i) {
-            register struct ttinfo *    ttisp;
-
-            ttisp = &sp->ttis[i];
-            if (ttisstdcnt == 0)
-                ttisp->tt_ttisstd = FALSE;
-            else {
-                ttisp->tt_ttisstd = *p++;
-                if (ttisp->tt_ttisstd != TRUE &&
-                    ttisp->tt_ttisstd != FALSE)
-                        goto oops;
-            }
-        }
-        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)
-                        goto oops;
-            }
-        }
-        /*
-        ** If this is an old file, we're done.
-        */
-        if (up->tzhead.tzh_version[0] == '\0')
-            break;
-        nread -= p - up->buf;
-        for (i = 0; i < nread; ++i)
-            up->buf[i] = p[i];
-        /*
-        ** If this is a signed narrow time_t system, we're done.
-        */
-        if (TYPE_SIGNED(time_t) && stored >= (int) sizeof(time_t))
-            break;
-    }
-    if (doextend && nread > 2 &&
-        up->buf[0] == '\n' && up->buf[nread - 1] == '\n' &&
-        sp->typecnt + 2 <= TZ_MAX_TYPES) {
-            struct state    *ts = &lsp->u.st;
-            register int result;
-
-            up->buf[nread - 1] = '\0';
-            result = tzparse(&up->buf[1], ts, FALSE);
-            if (result == 0 && ts->typecnt == 2 &&
-                sp->charcnt + ts->charcnt <= TZ_MAX_CHARS) {
-                    for (i = 0; i < 2; ++i)
-                        ts->ttis[i].tt_abbrind +=
-                            sp->charcnt;
-                    for (i = 0; i < ts->charcnt; ++i)
-                        sp->chars[sp->charcnt++] =
-                            ts->chars[i];
-                    i = 0;
-                    while (i < ts->timecnt &&
-                        ts->ats[i] <=
-                        sp->ats[sp->timecnt - 1])
-                            ++i;
-                    while (i < ts->timecnt &&
-                        sp->timecnt < TZ_MAX_TIMES) {
-                        sp->ats[sp->timecnt] =
-                            ts->ats[i];
-                        sp->types[sp->timecnt] =
-                            sp->typecnt +
-                            ts->types[i];
-                        ++sp->timecnt;
-                        ++i;
-                    }
-                    sp->ttis[sp->typecnt++] = ts->ttis[0];
-                    sp->ttis[sp->typecnt++] = ts->ttis[1];
-            }
-    }
-    if (sp->timecnt > 1) {
-        for (i = 1; i < sp->timecnt; ++i)
-            if (typesequiv(sp, sp->types[i], sp->types[0]) &&
-                    differ_by_repeat(sp->ats[i], sp->ats[0])) {
-                sp->goback = TRUE;
-                break;
-            }
-            for (i = sp->timecnt - 2; i >= 0; --i)
-                if (typesequiv(sp, sp->types[sp->timecnt - 1],
-                               sp->types[i]) &&
-                        differ_by_repeat(sp->ats[sp->timecnt - 1],
-                                         sp->ats[i])) {
-                    sp->goahead = TRUE;
-                    break;
-            }
-        }
-        /*
-        ** If type 0 is is unused in transitions,
-        ** it's the type to use for early times.
-        */
-        for (i = 0; i < sp->typecnt; ++i)
-            if (sp->types[i] == 0)
-                break;
-        i = (i >= sp->typecnt) ? 0 : -1;
-        /*
-        ** Absent the above,
-        ** if there are transition times
-        ** and the first transition is to a daylight time
-        ** find the standard type less than and closest to
-        ** the type of the first transition.
-        */
-        if (i < 0 && sp->timecnt > 0 && sp->ttis[sp->types[0]].tt_isdst) {
-            i = sp->types[0];
-            while (--i >= 0)
-                if (!sp->ttis[i].tt_isdst)
-                    break;
-        }
-        /*
-        ** If no result yet, find the first standard type.
-        ** If there is none, punt to type zero.
-        */
-        if (i < 0) {
-            i = 0;
-            while (sp->ttis[i].tt_isdst)
-                if (++i >= sp->typecnt) {
-                    i = 0;
-                    break;
-                }
-        }
-        sp->defaulttype = i;
-#ifdef ALL_STATE
-        free(up);
-#endif /* defined ALL_STATE */
-        return 0;
-oops:
-#ifdef ALL_STATE
-        free(up);
-#endif /* defined ALL_STATE */
-        return -1;
-}
-
-static int
-typesequiv(const struct state *const sp, const int a, const int b)
-{
-    register 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];
-        result = ap->tt_gmtoff == bp->tt_gmtoff &&
-            ap->tt_isdst == bp->tt_isdst &&
-            ap->tt_ttisstd == bp->tt_ttisstd &&
-            ap->tt_ttisgmt == bp->tt_ttisgmt &&
-            strcmp(&sp->chars[ap->tt_abbrind],
-            &sp->chars[bp->tt_abbrind]) == 0;
-    }
-    return result;
-}
-
-static const int mon_lengths[2][MONSPERYEAR] = {
-    { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
-    { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
+  /* The entire buffer.  */
+  char buf[2 * sizeof(struct tzhead) + 2 * sizeof (struct state)
+	   + 4 * TZ_MAX_TIMES];
 };
 
-static const int year_lengths[2] = {
-    DAYSPERNYEAR, DAYSPERLYEAR
+/* Local storage needed for 'tzloadbody'.  */
+union local_storage {
+  /* The file name to be opened.  */
+  char fullname[FILENAME_MAX + 1];
+
+  /* The results of analyzing the file's contents after it is opened.  */
+  struct {
+    /* The input buffer.  */
+    union input_buffer u;
+
+    /* A temporary state used for parsing a TZ string in the file.  */
+    struct state st;
+  } u;
+};
+
+static int __bionic_open_tzdata(const char*);
+
+/* Load tz data from the file named NAME into *SP.  Read extended
+   format if DOEXTEND.  Use *LSP for temporary storage.  Return 0 on
+   success, an errno value on failure.  */
+static int
+tzloadbody(char const *name, struct state *sp, bool doextend,
+	   union local_storage *lsp)
+{
+	register int			i;
+	register int			fid;
+	register int			stored;
+	register ssize_t		nread;
+#if !defined(__ANDROID__)
+	register bool doaccess;
+	register char *fullname = lsp->fullname;
+#endif
+	register union input_buffer *up = &lsp->u.u;
+	register int tzheadsize = sizeof (struct tzhead);
+
+	sp->goback = sp->goahead = false;
+
+	if (! name) {
+		name = TZDEFAULT;
+		if (! name)
+		  return EINVAL;
+	}
+
+#if defined(__ANDROID__)
+	fid = __bionic_open_tzdata(name);
+#else
+	if (name[0] == ':')
+		++name;
+	doaccess = name[0] == '/';
+	if (!doaccess) {
+		char const *p = TZDIR;
+		if (! p)
+		  return EINVAL;
+		if (sizeof lsp->fullname - 1 <= strlen(p) + strlen(name))
+		  return ENAMETOOLONG;
+		strcpy(fullname, p);
+		strcat(fullname, "/");
+		strcat(fullname, name);
+		/* Set doaccess if '.' (as in "../") shows up in name.  */
+		if (strchr(name, '.'))
+			doaccess = true;
+		name = fullname;
+	}
+	if (doaccess && access(name, R_OK) != 0)
+	  return errno;
+	fid = open(name, OPEN_MODE);
+#endif
+	if (fid < 0)
+	  return errno;
+
+	nread = read(fid, up->buf, sizeof up->buf);
+	if (nread < tzheadsize) {
+	  int err = nread < 0 ? errno : EINVAL;
+	  close(fid);
+	  return err;
+	}
+	if (close(fid) < 0)
+	  return errno;
+	for (stored = 4; stored <= 8; stored *= 2) {
+		int_fast32_t ttisstdcnt = detzcode(up->tzhead.tzh_ttisstdcnt);
+		int_fast32_t ttisgmtcnt = detzcode(up->tzhead.tzh_ttisgmtcnt);
+		int_fast32_t leapcnt = detzcode(up->tzhead.tzh_leapcnt);
+		int_fast32_t timecnt = detzcode(up->tzhead.tzh_timecnt);
+		int_fast32_t typecnt = detzcode(up->tzhead.tzh_typecnt);
+		int_fast32_t charcnt = detzcode(up->tzhead.tzh_charcnt);
+		char const *p = up->buf + tzheadsize;
+		if (! (0 <= leapcnt && leapcnt < TZ_MAX_LEAPS
+		       && 0 < typecnt && typecnt < TZ_MAX_TYPES
+		       && 0 <= timecnt && timecnt < TZ_MAX_TIMES
+		       && 0 <= charcnt && charcnt < TZ_MAX_CHARS
+		       && (ttisstdcnt == typecnt || ttisstdcnt == 0)
+		       && (ttisgmtcnt == typecnt || ttisgmtcnt == 0)))
+		  return EINVAL;
+		if (nread
+		    < (tzheadsize		/* struct tzhead */
+		       + timecnt * stored	/* ats */
+		       + timecnt		/* types */
+		       + typecnt * 6		/* ttinfos */
+		       + charcnt		/* chars */
+		       + leapcnt * (stored + 4)	/* lsinfos */
+		       + ttisstdcnt		/* ttisstds */
+		       + ttisgmtcnt))		/* ttisgmts */
+		  return EINVAL;
+		sp->leapcnt = leapcnt;
+		sp->timecnt = timecnt;
+		sp->typecnt = typecnt;
+		sp->charcnt = charcnt;
+
+		/* Read transitions, discarding those out of time_t range.
+		   But pretend the last transition before time_t_min
+		   occurred at time_t_min.  */
+		timecnt = 0;
+		for (i = 0; i < sp->timecnt; ++i) {
+			int_fast64_t at
+			  = stored == 4 ? detzcode(p) : detzcode64(p);
+			sp->types[i] = at <= time_t_max;
+			if (sp->types[i]) {
+			  time_t attime
+			    = ((TYPE_SIGNED(time_t) ? at < time_t_min : at < 0)
+			       ? time_t_min : at);
+			  if (timecnt && attime <= sp->ats[timecnt - 1]) {
+			    if (attime < sp->ats[timecnt - 1])
+			      return EINVAL;
+			    sp->types[i - 1] = 0;
+			    timecnt--;
+			  }
+			  sp->ats[timecnt++] = attime;
+			}
+			p += stored;
+		}
+
+		timecnt = 0;
+		for (i = 0; i < sp->timecnt; ++i) {
+			unsigned char typ = *p++;
+			if (sp->typecnt <= typ)
+			  return EINVAL;
+			if (sp->types[i])
+				sp->types[timecnt++] = typ;
+		}
+		sp->timecnt = timecnt;
+		for (i = 0; i < sp->typecnt; ++i) {
+			register struct ttinfo *	ttisp;
+			unsigned char isdst, abbrind;
+
+			ttisp = &sp->ttis[i];
+			ttisp->tt_gmtoff = detzcode(p);
+			p += 4;
+			isdst = *p++;
+			if (! (isdst < 2))
+			  return EINVAL;
+			ttisp->tt_isdst = isdst;
+			abbrind = *p++;
+			if (! (abbrind < sp->charcnt))
+			  return EINVAL;
+			ttisp->tt_abbrind = abbrind;
+		}
+		for (i = 0; i < sp->charcnt; ++i)
+			sp->chars[i] = *p++;
+		sp->chars[i] = '\0';	/* ensure '\0' at end */
+
+		/* Read leap seconds, discarding those out of time_t range.  */
+		leapcnt = 0;
+		for (i = 0; i < sp->leapcnt; ++i) {
+		  int_fast64_t tr = stored == 4 ? detzcode(p) : detzcode64(p);
+		  int_fast32_t corr = detzcode(p + stored);
+		  p += stored + 4;
+		  if (tr <= time_t_max) {
+		    time_t trans
+		      = ((TYPE_SIGNED(time_t) ? tr < time_t_min : tr < 0)
+			 ? time_t_min : tr);
+		    if (leapcnt && trans <= sp->lsis[leapcnt - 1].ls_trans) {
+		      if (trans < sp->lsis[leapcnt - 1].ls_trans)
+			return EINVAL;
+		      leapcnt--;
+		    }
+		    sp->lsis[leapcnt].ls_trans = trans;
+		    sp->lsis[leapcnt].ls_corr = corr;
+		    leapcnt++;
+		  }
+		}
+		sp->leapcnt = leapcnt;
+
+		for (i = 0; i < sp->typecnt; ++i) {
+			register struct ttinfo *	ttisp;
+
+			ttisp = &sp->ttis[i];
+			if (ttisstdcnt == 0)
+				ttisp->tt_ttisstd = false;
+			else {
+				if (*p != true && *p != false)
+				  return EINVAL;
+				ttisp->tt_ttisstd = *p++;
+			}
+		}
+		for (i = 0; i < sp->typecnt; ++i) {
+			register struct ttinfo *	ttisp;
+
+			ttisp = &sp->ttis[i];
+			if (ttisgmtcnt == 0)
+				ttisp->tt_ttisgmt = false;
+			else {
+				if (*p != true && *p != false)
+						return EINVAL;
+				ttisp->tt_ttisgmt = *p++;
+			}
+		}
+		/*
+		** If this is an old file, we're done.
+		*/
+		if (up->tzhead.tzh_version[0] == '\0')
+			break;
+		nread -= p - up->buf;
+		memmove(up->buf, p, nread);
+	}
+	if (doextend && nread > 2 &&
+		up->buf[0] == '\n' && up->buf[nread - 1] == '\n' &&
+		sp->typecnt + 2 <= TZ_MAX_TYPES) {
+			struct state	*ts = &lsp->u.st;
+
+			up->buf[nread - 1] = '\0';
+			if (tzparse(&up->buf[1], ts, false)
+			    && ts->typecnt == 2) {
+
+			  /* Attempt to reuse existing abbreviations.
+			     Without this, America/Anchorage would stop
+			     working after 2037 when TZ_MAX_CHARS is 50, as
+			     sp->charcnt equals 42 (for LMT CAT CAWT CAPT AHST
+			     AHDT YST AKDT AKST) and ts->charcnt equals 10
+			     (for AKST AKDT).  Reusing means sp->charcnt can
+			     stay 42 in this example.  */
+			  int gotabbr = 0;
+			  int charcnt = sp->charcnt;
+			  for (i = 0; i < 2; i++) {
+			    char *tsabbr = ts->chars + ts->ttis[i].tt_abbrind;
+			    int j;
+			    for (j = 0; j < charcnt; j++)
+			      if (strcmp(sp->chars + j, tsabbr) == 0) {
+				ts->ttis[i].tt_abbrind = j;
+				gotabbr++;
+				break;
+			      }
+			    if (! (j < charcnt)) {
+			      int tsabbrlen = strlen(tsabbr);
+			      if (j + tsabbrlen < TZ_MAX_CHARS) {
+				strcpy(sp->chars + j, tsabbr);
+				charcnt = j + tsabbrlen + 1;
+				ts->ttis[i].tt_abbrind = j;
+				gotabbr++;
+			      }
+			    }
+			  }
+			  if (gotabbr == 2) {
+			    sp->charcnt = charcnt;
+			    for (i = 0; i < ts->timecnt; i++)
+			      if (sp->ats[sp->timecnt - 1] < ts->ats[i])
+				break;
+			    while (i < ts->timecnt
+				   && sp->timecnt < TZ_MAX_TIMES) {
+			      sp->ats[sp->timecnt] = ts->ats[i];
+			      sp->types[sp->timecnt] = (sp->typecnt
+							+ ts->types[i]);
+			      sp->timecnt++;
+			      i++;
+			    }
+			    sp->ttis[sp->typecnt++] = ts->ttis[0];
+			    sp->ttis[sp->typecnt++] = ts->ttis[1];
+			  }
+			}
+	}
+	if (sp->timecnt > 1) {
+		for (i = 1; i < sp->timecnt; ++i)
+			if (typesequiv(sp, sp->types[i], sp->types[0]) &&
+				differ_by_repeat(sp->ats[i], sp->ats[0])) {
+					sp->goback = true;
+					break;
+				}
+		for (i = sp->timecnt - 2; i >= 0; --i)
+			if (typesequiv(sp, sp->types[sp->timecnt - 1],
+				sp->types[i]) &&
+				differ_by_repeat(sp->ats[sp->timecnt - 1],
+				sp->ats[i])) {
+					sp->goahead = true;
+					break;
+		}
+	}
+	/*
+	** If type 0 is is unused in transitions,
+	** it's the type to use for early times.
+	*/
+	for (i = 0; i < sp->timecnt; ++i)
+		if (sp->types[i] == 0)
+			break;
+	i = i < sp->timecnt ? -1 : 0;
+	/*
+	** Absent the above,
+	** if there are transition times
+	** and the first transition is to a daylight time
+	** find the standard type less than and closest to
+	** the type of the first transition.
+	*/
+	if (i < 0 && sp->timecnt > 0 && sp->ttis[sp->types[0]].tt_isdst) {
+		i = sp->types[0];
+		while (--i >= 0)
+			if (!sp->ttis[i].tt_isdst)
+				break;
+	}
+	/*
+	** If no result yet, find the first standard type.
+	** If there is none, punt to type zero.
+	*/
+	if (i < 0) {
+		i = 0;
+		while (sp->ttis[i].tt_isdst)
+			if (++i >= sp->typecnt) {
+				i = 0;
+				break;
+			}
+	}
+	sp->defaulttype = i;
+	return 0;
+}
+
+/* Load tz data from the file named NAME into *SP.  Read extended
+   format if DOEXTEND.  Return 0 on success, an errno value on failure.  */
+static int
+tzload(char const *name, struct state *sp, bool doextend)
+{
+#ifdef ALL_STATE
+  union local_storage *lsp = malloc(sizeof *lsp);
+  if (!lsp)
+    return errno;
+  else {
+    int err = tzloadbody(name, sp, doextend, lsp);
+    free(lsp);
+    return err;
+  }
+#else
+  union local_storage ls;
+  return tzloadbody(name, sp, doextend, &ls);
+#endif
+}
+
+static bool
+typesequiv(const struct state *sp, int a, int b)
+{
+	register bool 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];
+		result = ap->tt_gmtoff == bp->tt_gmtoff &&
+			ap->tt_isdst == bp->tt_isdst &&
+			ap->tt_ttisstd == bp->tt_ttisstd &&
+			ap->tt_ttisgmt == bp->tt_ttisgmt &&
+			strcmp(&sp->chars[ap->tt_abbrind],
+			&sp->chars[bp->tt_abbrind]) == 0;
+	}
+	return result;
+}
+
+static const int	mon_lengths[2][MONSPERYEAR] = {
+	{ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
+	{ 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
+};
+
+static const int	year_lengths[2] = {
+	DAYSPERNYEAR, DAYSPERLYEAR
 };
 
 /*
@@ -658,15 +732,15 @@
 ** character.
 */
 
-static const char *
-getzname(register const char * strp)
+static const char * ATTRIBUTE_PURE
+getzname(register const char *strp)
 {
-    register char   c;
+	register char	c;
 
-    while ((c = *strp) != '\0' && !is_digit(c) && c != ',' && c != '-' &&
-        c != '+')
-            ++strp;
-    return strp;
+	while ((c = *strp) != '\0' && !is_digit(c) && c != ',' && c != '-' &&
+		c != '+')
+			++strp;
+	return strp;
 }
 
 /*
@@ -678,14 +752,14 @@
 ** We don't do any checking here; checking is done later in common-case code.
 */
 
-static const char *
+static const char * ATTRIBUTE_PURE
 getqzname(register const char *strp, const int delim)
 {
-    register int c;
+	register int	c;
 
-    while ((c = *strp) != '\0' && c != delim)
-        ++strp;
-    return strp;
+	while ((c = *strp) != '\0' && c != delim)
+		++strp;
+	return strp;
 }
 
 /*
@@ -696,24 +770,24 @@
 */
 
 static const char *
-getnum(register const char * strp, int * const nump, const int min, const int max)
+getnum(register const char *strp, int *const nump, const int min, const int max)
 {
-    register char c;
-    register int  num;
+	register char	c;
+	register int	num;
 
-    if (strp == NULL || !is_digit(c = *strp))
-        return NULL;
-    num = 0;
-    do {
-        num = num * 10 + (c - '0');
-        if (num > max)
-            return NULL;    /* illegal value */
-        c = *++strp;
-    } while (is_digit(c));
-    if (num < min)
-        return NULL;        /* illegal value */
-    *nump = num;
-    return strp;
+	if (strp == NULL || !is_digit(c = *strp))
+		return NULL;
+	num = 0;
+	do {
+		num = num * 10 + (c - '0');
+		if (num > max)
+			return NULL;	/* illegal value */
+		c = *++strp;
+	} while (is_digit(c));
+	if (num < min)
+		return NULL;		/* illegal value */
+	*nump = num;
+	return strp;
 }
 
 /*
@@ -727,34 +801,34 @@
 static const char *
 getsecs(register const char *strp, int_fast32_t *const secsp)
 {
-    int num;
+	int	num;
 
-    /*
-    ** '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 * (int_fast32_t) SECSPERHOUR;
-    if (*strp == ':') {
-        ++strp;
-        strp = getnum(strp, &num, 0, MINSPERHOUR - 1);
-        if (strp == NULL)
-            return NULL;
-        *secsp += num * SECSPERMIN;
-        if (*strp == ':') {
-            ++strp;
-            /* 'SECSPERMIN' allows for leap seconds. */
-            strp = getnum(strp, &num, 0, SECSPERMIN);
-            if (strp == NULL)
-                return NULL;
-            *secsp += num;
-        }
-    }
-    return strp;
+	/*
+	** '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 * (int_fast32_t) SECSPERHOUR;
+	if (*strp == ':') {
+		++strp;
+		strp = getnum(strp, &num, 0, MINSPERHOUR - 1);
+		if (strp == NULL)
+			return NULL;
+		*secsp += num * SECSPERMIN;
+		if (*strp == ':') {
+			++strp;
+			/* 'SECSPERMIN' allows for leap seconds.  */
+			strp = getnum(strp, &num, 0, SECSPERMIN);
+			if (strp == NULL)
+				return NULL;
+			*secsp += num;
+		}
+	}
+	return strp;
 }
 
 /*
@@ -767,19 +841,19 @@
 static const char *
 getoffset(register const char *strp, int_fast32_t *const offsetp)
 {
-    register int neg = 0;
+	register bool neg = false;
 
-    if (*strp == '-') {
-        neg = 1;
-        ++strp;
-    } else if (*strp == '+')
-        ++strp;
-    strp = getsecs(strp, offsetp);
-    if (strp == NULL)
-        return NULL;        /* illegal time */
-    if (neg)
-        *offsetp = -*offsetp;
-    return strp;
+	if (*strp == '-') {
+		neg = true;
+		++strp;
+	} else if (*strp == '+')
+		++strp;
+	strp = getsecs(strp, offsetp);
+	if (strp == NULL)
+		return NULL;		/* illegal time */
+	if (neg)
+		*offsetp = -*offsetp;
+	return strp;
 }
 
 /*
@@ -790,49 +864,49 @@
 */
 
 static const char *
-getrule(const char * strp, register struct rule * const rulep)
+getrule(const char *strp, register struct rule *const rulep)
 {
-    if (*strp == 'J') {
-        /*
-        ** Julian day.
-        */
-        rulep->r_type = JULIAN_DAY;
-        ++strp;
-        strp = getnum(strp, &rulep->r_day, 1, DAYSPERNYEAR);
-    } else if (*strp == 'M') {
-        /*
-        ** Month, week, day.
-        */
-        rulep->r_type = MONTH_NTH_DAY_OF_WEEK;
-        ++strp;
-        strp = getnum(strp, &rulep->r_mon, 1, MONSPERYEAR);
-        if (strp == NULL)
-            return NULL;
-        if (*strp++ != '.')
-            return NULL;
-        strp = getnum(strp, &rulep->r_week, 1, 5);
-        if (strp == NULL)
-            return NULL;
-        if (*strp++ != '.')
-            return NULL;
-        strp = getnum(strp, &rulep->r_day, 0, DAYSPERWEEK - 1);
-    } else if (is_digit(*strp)) {
-        /*
-        ** Day of year.
-        */
-        rulep->r_type = DAY_OF_YEAR;
-        strp = getnum(strp, &rulep->r_day, 0, DAYSPERLYEAR - 1);
-    } else  return NULL;        /* invalid format */
-    if (strp == NULL)
-        return NULL;
-    if (*strp == '/') {
-        /*
-        ** Time specified.
-        */
-        ++strp;
-        strp = getoffset(strp, &rulep->r_time);
-    } else  rulep->r_time = 2 * SECSPERHOUR;    /* default = 2:00:00 */
-    return strp;
+	if (*strp == 'J') {
+		/*
+		** Julian day.
+		*/
+		rulep->r_type = JULIAN_DAY;
+		++strp;
+		strp = getnum(strp, &rulep->r_day, 1, DAYSPERNYEAR);
+	} else if (*strp == 'M') {
+		/*
+		** Month, week, day.
+		*/
+		rulep->r_type = MONTH_NTH_DAY_OF_WEEK;
+		++strp;
+		strp = getnum(strp, &rulep->r_mon, 1, MONSPERYEAR);
+		if (strp == NULL)
+			return NULL;
+		if (*strp++ != '.')
+			return NULL;
+		strp = getnum(strp, &rulep->r_week, 1, 5);
+		if (strp == NULL)
+			return NULL;
+		if (*strp++ != '.')
+			return NULL;
+		strp = getnum(strp, &rulep->r_day, 0, DAYSPERWEEK - 1);
+	} else if (is_digit(*strp)) {
+		/*
+		** Day of year.
+		*/
+		rulep->r_type = DAY_OF_YEAR;
+		strp = getnum(strp, &rulep->r_day, 0, DAYSPERLYEAR - 1);
+	} else	return NULL;		/* invalid format */
+	if (strp == NULL)
+		return NULL;
+	if (*strp == '/') {
+		/*
+		** Time specified.
+		*/
+		++strp;
+		strp = getoffset(strp, &rulep->r_time);
+	} else	rulep->r_time = 2 * SECSPERHOUR;	/* default = 2:00:00 */
+	return strp;
 }
 
 /*
@@ -840,11 +914,11 @@
 ** effect, calculate the year-relative time that rule takes effect.
 */
 
-static int_fast32_t
+static int_fast32_t ATTRIBUTE_PURE
 transtime(const int year, register const struct rule *const rulep,
           const int_fast32_t offset)
 {
-    register int          leapyear;
+    register bool         leapyear;
     register int_fast32_t value;
     register int          i;
     int d, m1, yy0, yy1, yy2, dow;
@@ -931,477 +1005,537 @@
 ** appropriate.
 */
 
-static int
-tzparse(const char * name, register struct state * const sp,
-        const int lastditch)
+static bool
+tzparse(const char *name, struct state *sp, bool lastditch)
 {
-    const char *         stdname;
-    const char *         dstname;
-    size_t               stdlen;
-    size_t               dstlen;
-    int_fast32_t         stdoffset;
-    int_fast32_t         dstoffset;
-    register char *      cp;
-    register int         load_result;
-    static struct ttinfo zttinfo;
+	const char *			stdname;
+	const char *			dstname;
+	size_t				stdlen;
+	size_t				dstlen;
+	size_t				charcnt;
+	int_fast32_t			stdoffset;
+	int_fast32_t			dstoffset;
+	register char *			cp;
+	register bool			load_ok;
 
-    stdname = name;
-    if (lastditch) {
-        stdlen = strlen(name);  /* length of standard zone name */
-        name += stdlen;
-        if (stdlen >= sizeof sp->chars)
-            stdlen = (sizeof sp->chars) - 1;
-        stdoffset = 0;
-    } else {
-        if (*name == '<') {
-            name++;
-            stdname = name;
-            name = getqzname(name, '>');
-            if (*name != '>')
-                return (-1);
-            stdlen = name - stdname;
-            name++;
-        } else {
-            name = getzname(name);
-            stdlen = name - stdname;
-        }
-        if (*name == '\0')
-            return -1;
-        name = getoffset(name, &stdoffset);
-        if (name == NULL)
-            return -1;
-    }
-    load_result = tzload(TZDEFRULES, sp, FALSE);
-    if (load_result != 0)
-        sp->leapcnt = 0;        /* so, we're off a little */
-    if (*name != '\0') {
-        if (*name == '<') {
-            dstname = ++name;
-            name = getqzname(name, '>');
-            if (*name != '>')
-                return -1;
-            dstlen = name - dstname;
-            name++;
-        } else {
-            dstname = name;
-            name = getzname(name);
-            dstlen = name - dstname; /* length of DST zone name */
-        }
-        if (*name != '\0' && *name != ',' && *name != ';') {
-            name = getoffset(name, &dstoffset);
-            if (name == NULL)
-                return -1;
-        } else  dstoffset = stdoffset - SECSPERHOUR;
-        if (*name == '\0' && load_result != 0)
-            name = TZDEFRULESTRING;
-        if (*name == ',' || *name == ';') {
-            struct rule  start;
-            struct rule  end;
-            register int year;
-            register int yearlim;
-            register int timecnt;
-            time_t       janfirst;
+	stdname = name;
+	if (lastditch) {
+		stdlen = sizeof gmt - 1;
+		name += stdlen;
+		stdoffset = 0;
+	} else {
+		if (*name == '<') {
+			name++;
+			stdname = name;
+			name = getqzname(name, '>');
+			if (*name != '>')
+			  return false;
+			stdlen = name - stdname;
+			name++;
+		} else {
+			name = getzname(name);
+			stdlen = name - stdname;
+		}
+		if (!stdlen)
+		  return false;
+		name = getoffset(name, &stdoffset);
+		if (name == NULL)
+		  return false;
+	}
+	charcnt = stdlen + 1;
+	if (sizeof sp->chars < charcnt)
+	  return false;
+	load_ok = tzload(TZDEFRULES, sp, false) == 0;
+	if (!load_ok)
+		sp->leapcnt = 0;		/* so, we're off a little */
+	if (*name != '\0') {
+		if (*name == '<') {
+			dstname = ++name;
+			name = getqzname(name, '>');
+			if (*name != '>')
+			  return false;
+			dstlen = name - dstname;
+			name++;
+		} else {
+			dstname = name;
+			name = getzname(name);
+			dstlen = name - dstname; /* length of DST zone name */
+		}
+		if (!dstlen)
+		  return false;
+		charcnt += dstlen + 1;
+		if (sizeof sp->chars < charcnt)
+		  return false;
+		if (*name != '\0' && *name != ',' && *name != ';') {
+			name = getoffset(name, &dstoffset);
+			if (name == NULL)
+			  return false;
+		} else	dstoffset = stdoffset - SECSPERHOUR;
+		if (*name == '\0' && !load_ok)
+			name = TZDEFRULESTRING;
+		if (*name == ',' || *name == ';') {
+			struct rule	start;
+			struct rule	end;
+			register int	year;
+			register int	yearlim;
+			register int	timecnt;
+			time_t		janfirst;
 
-            ++name;
-            if ((name = getrule(name, &start)) == NULL)
-                return -1;
-            if (*name++ != ',')
-                return -1;
-            if ((name = getrule(name, &end)) == NULL)
-                return -1;
-            if (*name != '\0')
-                return -1;
-            sp->typecnt = 2;    /* standard time and DST */
-            /*
-            ** Two transitions per year, from EPOCH_YEAR forward.
-            */
-            sp->ttis[0] = sp->ttis[1] = zttinfo;
-            sp->ttis[0].tt_gmtoff = -dstoffset;
-            sp->ttis[0].tt_isdst = 1;
-            sp->ttis[0].tt_abbrind = stdlen + 1;
-            sp->ttis[1].tt_gmtoff = -stdoffset;
-            sp->ttis[1].tt_isdst = 0;
-            sp->ttis[1].tt_abbrind = 0;
-            sp->defaulttype = 0;
-            timecnt = 0;
-            janfirst = 0;
-            yearlim = EPOCH_YEAR + YEARSPERREPEAT;
-            for (year = EPOCH_YEAR; year < yearlim; year++) {
-                int_fast32_t
-                  starttime = transtime(year, &start, stdoffset),
-                  endtime = transtime(year, &end, dstoffset);
-                int_fast32_t
-                yearsecs = (year_lengths[isleap(year)]
-                            * SECSPERDAY);
-                int reversed = endtime < starttime;
-                if (reversed) {
-                    int_fast32_t swap = starttime;
-                    starttime = endtime;
-                    endtime = swap;
-                }
-                if (reversed
-                    || (starttime < endtime
-                        && (endtime - starttime
-                            < (yearsecs
-                               + (stdoffset - dstoffset))))) {
-                    if (TZ_MAX_TIMES - 2 < timecnt)
-                        break;
-                    yearlim = year + YEARSPERREPEAT + 1;
-                    sp->ats[timecnt] = janfirst;
-                    if (increment_overflow_time
-                        (&sp->ats[timecnt], starttime))
-                        break;
-                    sp->types[timecnt++] = reversed;
-                    sp->ats[timecnt] = janfirst;
-                    if (increment_overflow_time
-                        (&sp->ats[timecnt], endtime))
-                        break;
-                    sp->types[timecnt++] = !reversed;
-                    }
-                if (increment_overflow_time(&janfirst, yearsecs))
-                    break;
-            }
-            sp->timecnt = timecnt;
-            if (!timecnt)
-                sp->typecnt = 1;    /* Perpetual DST.  */
-        } else {
-            register int_fast32_t   theirstdoffset;
-            register int_fast32_t   theirdstoffset;
-            register int_fast32_t   theiroffset;
-            register int    isdst;
-            register int    i;
-            register int    j;
+			++name;
+			if ((name = getrule(name, &start)) == NULL)
+			  return false;
+			if (*name++ != ',')
+			  return false;
+			if ((name = getrule(name, &end)) == NULL)
+			  return false;
+			if (*name != '\0')
+			  return false;
+			sp->typecnt = 2;	/* standard time and DST */
+			/*
+			** Two transitions per year, from EPOCH_YEAR forward.
+			*/
+			init_ttinfo(&sp->ttis[0], -dstoffset, true, stdlen + 1);
+			init_ttinfo(&sp->ttis[1], -stdoffset, false, 0);
+			sp->defaulttype = 0;
+			timecnt = 0;
+			janfirst = 0;
+			yearlim = EPOCH_YEAR + YEARSPERREPEAT;
+			for (year = EPOCH_YEAR; year < yearlim; year++) {
+				int_fast32_t
+				  starttime = transtime(year, &start, stdoffset),
+				  endtime = transtime(year, &end, dstoffset);
+				int_fast32_t
+				  yearsecs = (year_lengths[isleap(year)]
+					      * SECSPERDAY);
+				bool reversed = endtime < starttime;
+				if (reversed) {
+					int_fast32_t swap = starttime;
+					starttime = endtime;
+					endtime = swap;
+				}
+				if (reversed
+				    || (starttime < endtime
+					&& (endtime - starttime
+					    < (yearsecs
+					       + (stdoffset - dstoffset))))) {
+					if (TZ_MAX_TIMES - 2 < timecnt)
+						break;
+					yearlim = year + YEARSPERREPEAT + 1;
+					sp->ats[timecnt] = janfirst;
+					if (increment_overflow_time
+					    (&sp->ats[timecnt], starttime))
+						break;
+					sp->types[timecnt++] = reversed;
+					sp->ats[timecnt] = janfirst;
+					if (increment_overflow_time
+					    (&sp->ats[timecnt], endtime))
+						break;
+					sp->types[timecnt++] = !reversed;
+				}
+				if (increment_overflow_time(&janfirst, yearsecs))
+					break;
+			}
+			sp->timecnt = timecnt;
+			if (!timecnt)
+				sp->typecnt = 1;	/* Perpetual DST.  */
+		} else {
+			register int_fast32_t	theirstdoffset;
+			register int_fast32_t	theirdstoffset;
+			register int_fast32_t	theiroffset;
+			register bool		isdst;
+			register int		i;
+			register int		j;
 
-            if (*name != '\0')
-                return -1;
-            /*
-            ** Initial values of theirstdoffset and theirdstoffset.
-            */
-            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;
-                }
-            }
-            /*
-            ** Initially we're assumed to be in standard time.
-            */
-            isdst = FALSE;
-            theiroffset = theirstdoffset;
-            /*
-            ** Now juggle transition times and types
-            ** tracking offsets as you do.
-            */
-            for (i = 0; i < sp->timecnt; ++i) {
-                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.
-            */
-            sp->ttis[0] = sp->ttis[1] = zttinfo;
-            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;
-            sp->typecnt = 2;
-            sp->defaulttype = 0;
-        }
-    } else {
-        dstlen = 0;
-        sp->typecnt = 1;        /* only standard time */
-        sp->timecnt = 0;
-        sp->ttis[0] = zttinfo;
-        sp->ttis[0].tt_gmtoff = -stdoffset;
-        sp->ttis[0].tt_isdst = 0;
-        sp->ttis[0].tt_abbrind = 0;
-        sp->defaulttype = 0;
-    }
-    sp->charcnt = stdlen + 1;
-    if (dstlen != 0)
-        sp->charcnt += dstlen + 1;
-    if ((size_t) sp->charcnt > sizeof sp->chars)
-        return -1;
-    cp = sp->chars;
-    (void) strncpy(cp, stdname, stdlen);
-    cp += stdlen;
-    *cp++ = '\0';
-    if (dstlen != 0) {
-        (void) strncpy(cp, dstname, dstlen);
-        *(cp + dstlen) = '\0';
-    }
-    return 0;
+			if (*name != '\0')
+			  return false;
+			/*
+			** Initial values of theirstdoffset and theirdstoffset.
+			*/
+			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;
+				}
+			}
+			/*
+			** Initially we're assumed to be in standard time.
+			*/
+			isdst = false;
+			theiroffset = theirstdoffset;
+			/*
+			** Now juggle transition times and types
+			** tracking offsets as you do.
+			*/
+			for (i = 0; i < sp->timecnt; ++i) {
+				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.
+			*/
+			init_ttinfo(&sp->ttis[0], -stdoffset, false, 0);
+			init_ttinfo(&sp->ttis[1], -dstoffset, true, stdlen + 1);
+			sp->typecnt = 2;
+			sp->defaulttype = 0;
+		}
+	} else {
+		dstlen = 0;
+		sp->typecnt = 1;		/* only standard time */
+		sp->timecnt = 0;
+		init_ttinfo(&sp->ttis[0], -stdoffset, false, 0);
+		sp->defaulttype = 0;
+	}
+	sp->charcnt = charcnt;
+	cp = sp->chars;
+	memcpy(cp, stdname, stdlen);
+	cp += stdlen;
+	*cp++ = '\0';
+	if (dstlen != 0) {
+		memcpy(cp, dstname, dstlen);
+		*(cp + dstlen) = '\0';
+	}
+	return true;
 }
 
 static void
-gmtload(struct state * const sp)
+gmtload(struct state *const sp)
 {
-    if (tzload(gmt, sp, TRUE) != 0)
-        (void) tzparse(gmt, sp, TRUE);
+	if (tzload(gmt, sp, true) != 0)
+		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 */
+/* Initialize *SP to a value appropriate for the TZ setting NAME.
+   Return 0 on success, an errno value on failure.  */
+static int
+zoneinit(struct state *sp, char const *name)
+{
+  if (name && ! name[0]) {
+    /*
+    ** User wants it fast rather than right.
+    */
+    sp->leapcnt = 0;		/* so, we're off a little */
+    sp->timecnt = 0;
+    sp->typecnt = 0;
+    sp->charcnt = 0;
+    sp->goback = sp->goahead = false;
+    init_ttinfo(&sp->ttis[0], 0, false, 0);
+    strcpy(sp->chars, gmt);
+    sp->defaulttype = 0;
+    return 0;
+  } else {
+    int err = tzload(name, sp, true);
+    if (err != 0 && name && name[0] != ':' && tzparse(name, sp, false))
+      err = 0;
+    if (err == 0)
+      scrub_abbrs(sp);
+    return err;
+  }
+}
+
+static void
+tzsetlcl(char const *name)
+{
+  struct state *sp = lclptr;
+  int lcl = name ? strlen(name) < sizeof lcl_TZname : -1;
+  if (lcl < 0
+      ? lcl_is_set < 0
+      : 0 < lcl_is_set && strcmp(lcl_TZname, name) == 0)
+    return;
+#ifdef ALL_STATE
+  if (! sp)
+    lclptr = sp = malloc(sizeof *lclptr);
+#endif /* defined ALL_STATE */
+  if (sp) {
+    if (zoneinit(sp, name) != 0)
+      zoneinit(sp, "");
+    if (0 < lcl)
+      strcpy(lcl_TZname, name);
+  }
+  settzname();
+  lcl_is_set = lcl;
+}
+
+#ifdef STD_INSPIRED
 void
 tzsetwall(void)
 {
-    if (lcl_is_set < 0)
-        return;
-    lcl_is_set = -1;
-
-#ifdef ALL_STATE
-    if (lclptr == NULL) {
-        lclptr = malloc(sizeof *lclptr);
-        if (lclptr == NULL) {
-            settzname();    /* all we can do */
-            return;
-        }
-    }
-#endif /* defined ALL_STATE */
-    if (tzload(NULL, lclptr, TRUE) != 0)
-        gmtload(lclptr);
-    settzname();
+  if (lock() != 0)
+    return;
+  tzsetlcl(NULL);
+  unlock();
 }
+#endif
 
-#include <stdbool.h>
+#if defined(__ANDROID__)
 #define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
 #include <sys/_system_properties.h> // For __system_property_serial.
+#endif
 
 static void
-tzset_locked(void)
+tzset_unlocked(void)
 {
-    register const char * name;
+#if defined(__ANDROID__)
+  const char * name = getenv("TZ");
 
-    name = getenv("TZ");
+  // Try the "persist.sys.timezone" system property.
+  if (name == NULL) {
+    static const prop_info *pi;
 
-    // try the "persist.sys.timezone" system property first
-    if (name == NULL) {
-        static const prop_info *pi;
-
-        if (!pi) {
-            pi = __system_property_find("persist.sys.timezone");
-        }
-        if (pi) {
-            static char buf[PROP_VALUE_MAX];
-            static uint32_t s = -1;
-            static bool ok = false;
-            uint32_t serial;
-
-            serial = __system_property_serial(pi);
-            if (serial != s) {
-                ok = __system_property_read(pi, 0, buf) > 0;
-                s = serial;
-            }
-            if (ok) {
-                name = buf;
-            }
-        }
+    if (!pi) {
+      pi = __system_property_find("persist.sys.timezone");
     }
-
-    if (name == NULL) {
-        tzsetwall();
-        return;
+    if (pi) {
+      static char buf[PROP_VALUE_MAX];
+      static uint32_t s = -1;
+      static bool ok = false;
+      uint32_t serial = __system_property_serial(pi);
+      if (serial != s) {
+        ok = __system_property_read(pi, 0, buf) > 0;
+        s = serial;
+      }
+      if (ok) {
+        name = buf;
+      }
     }
+  }
 
-    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 = malloc(sizeof *lclptr);
-        if (lclptr == NULL) {
-            settzname();    /* all we can do */
-            return;
-        }
-    }
-#endif /* defined ALL_STATE */
-    if (*name == '\0') {
-        /*
-        ** User wants it fast rather than right.
-        */
-        lclptr->leapcnt = 0;        /* so, we're off a little */
-        lclptr->timecnt = 0;
-        lclptr->typecnt = 0;
-        lclptr->ttis[0].tt_isdst = 0;
-        lclptr->ttis[0].tt_gmtoff = 0;
-        lclptr->ttis[0].tt_abbrind = 0;
-        (void) strcpy(lclptr->chars, gmt);
-        lclptr->defaulttype = 0;
-    } else if (tzload(name, lclptr, TRUE) != 0)
-        if (name[0] == ':' || tzparse(name, lclptr, FALSE) != 0)
-            (void) gmtload(lclptr);
-    settzname();
+  tzsetlcl(name);
+#else
+  tzsetlcl(getenv("TZ"));
+#endif
 }
 
 void
 tzset(void)
 {
-    _tzLock();
-    tzset_locked();
-    _tzUnlock();
+  if (lock() != 0)
+    return;
+  tzset_unlocked();
+  unlock();
+}
+
+static void
+gmtcheck(void)
+{
+  static bool gmt_is_set;
+  if (lock() != 0)
+    return;
+  if (! gmt_is_set) {
+#ifdef ALL_STATE
+    gmtptr = malloc(sizeof *gmtptr);
+#endif
+    if (gmtptr)
+      gmtload(gmtptr);
+    gmt_is_set = true;
+  }
+  unlock();
+}
+
+#if NETBSD_INSPIRED
+
+timezone_t
+tzalloc(char const *name)
+{
+  timezone_t sp = malloc(sizeof *sp);
+  if (sp) {
+    int err = zoneinit(sp, name);
+    if (err != 0) {
+      free(sp);
+      errno = err;
+      return NULL;
+    }
+  }
+  return sp;
+}
+
+void
+tzfree(timezone_t sp)
+{
+  free(sp);
 }
 
 /*
+** NetBSD 6.1.4 has ctime_rz, but omit it because POSIX says ctime and
+** ctime_r are obsolescent and have potential security problems that
+** ctime_rz would share.  Callers can instead use localtime_rz + strftime.
+**
+** NetBSD 6.1.4 has tzgetname, but omit it because it doesn't work
+** in zones with three or more time zone abbreviations.
+** Callers can instead use localtime_rz + strftime.
+*/
+
+#endif
+
+/*
 ** The easy way to behave "as if no library function calls" localtime
-** is to not call it--so we drop its guts into "localsub", which can be
-** freely called. (And no, the PANS doesn't require the above behavior--
+** is to not call it, so we drop its guts into "localsub", which can be
+** freely called. (And no, the PANS doesn't require the above behavior,
 ** but it *is* desirable.)
 **
-** The unused offset argument is for the benefit of mktime variants.
+** If successful and SETNAME is nonzero,
+** set the applicable parts of tzname, timezone and altzone;
+** however, it's OK to omit this step if the time zone is POSIX-compatible,
+** since in that case tzset should have already done this step correctly.
+** SETNAME's type is intfast32_t for compatibility with gmtsub,
+** but it is actually a boolean and its value should be 0 or 1.
 */
 
 /*ARGSUSED*/
 static struct tm *
-localsub(const time_t * const timep, const int_fast32_t offset,
-         struct tm * const tmp, struct state * sp) // android-changed: added sp.
+localsub(struct state const *sp, time_t const *timep, int_fast32_t setname,
+	 struct tm *const tmp)
 {
-    register const struct ttinfo * ttisp;
-    register int         i;
-    register struct tm * result;
-    const time_t         t = *timep;
+	register const struct ttinfo *	ttisp;
+	register int			i;
+	register struct tm *		result;
+	const time_t			t = *timep;
 
-    // BEGIN android-changed: support user-supplied sp.
-    if (sp == NULL) {
-        sp = lclptr;
-    }
-    // END android-changed
-    if (sp == NULL)
-        return gmtsub(timep, offset, tmp, sp); // android-changed: added sp.
-    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 years;
+	if (sp == NULL) {
+	  /* Don't bother to set tzname etc.; tzset has already done it.  */
+	  return gmtsub(gmtptr, timep, 0, tmp);
+	}
+	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		years;
 
-            if (t < sp->ats[0])
-                seconds = sp->ats[0] - t;
-            else    seconds = t - sp->ats[sp->timecnt - 1];
-            --seconds;
-            years = (seconds / SECSPERREPEAT + 1) * YEARSPERREPEAT;
-            seconds = years * AVGSECSPERYEAR;
-            if (t < sp->ats[0])
-                newt += seconds;
-            else    newt -= seconds;
-            if (newt < sp->ats[0] ||
-                newt > sp->ats[sp->timecnt - 1])
-                    return NULL;    /* "cannot happen" */
-            result = localsub(&newt, offset, tmp, sp); // android-changed: added sp.
-            if (result == tmp) {
-                register time_t newy;
+			if (t < sp->ats[0])
+				seconds = sp->ats[0] - t;
+			else	seconds = t - sp->ats[sp->timecnt - 1];
+			--seconds;
+			years = (seconds / SECSPERREPEAT + 1) * YEARSPERREPEAT;
+			seconds = years * AVGSECSPERYEAR;
+			if (t < sp->ats[0])
+				newt += seconds;
+			else	newt -= seconds;
+			if (newt < sp->ats[0] ||
+				newt > sp->ats[sp->timecnt - 1])
+					return NULL;	/* "cannot happen" */
+			result = localsub(sp, &newt, setname, tmp);
+			if (result) {
+				register int_fast64_t newy;
 
-                newy = tmp->tm_year;
-                if (t < sp->ats[0])
-                    newy -= years;
-                else    newy += years;
-                tmp->tm_year = newy;
-                if (tmp->tm_year != newy)
-                    return NULL;
-            }
-            return result;
-    }
-    if (sp->timecnt == 0 || t < sp->ats[0]) {
-        i = sp->defaulttype;
-    } else {
-        register int lo = 1;
-        register int hi = sp->timecnt;
+				newy = result->tm_year;
+				if (t < sp->ats[0])
+					newy -= years;
+				else	newy += years;
+				if (! (INT_MIN <= newy && newy <= INT_MAX))
+					return NULL;
+				result->tm_year = newy;
+			}
+			return result;
+	}
+	if (sp->timecnt == 0 || t < sp->ats[0]) {
+		i = sp->defaulttype;
+	} else {
+		register int	lo = 1;
+		register int	hi = sp->timecnt;
 
-        while (lo < hi) {
-            register int    mid = (lo + hi) >> 1;
+		while (lo < hi) {
+			register int	mid = (lo + hi) >> 1;
 
-            if (t < sp->ats[mid])
-                hi = mid;
-            else    lo = mid + 1;
-        }
-        i = (int) sp->types[lo - 1];
-    }
-    ttisp = &sp->ttis[i];
-    /*
-    ** To get (wrong) behavior that's compatible with System V Release 2.0
-    ** you'd replace the statement below with
-    **  t += ttisp->tt_gmtoff;
-    **  timesub(&t, 0L, sp, tmp);
-    */
-    result = timesub(&t, ttisp->tt_gmtoff, sp, tmp);
-    tmp->tm_isdst = ttisp->tt_isdst;
-    tzname[tmp->tm_isdst] = &sp->chars[ttisp->tt_abbrind];
+			if (t < sp->ats[mid])
+				hi = mid;
+			else	lo = mid + 1;
+		}
+		i = (int) sp->types[lo - 1];
+	}
+	ttisp = &sp->ttis[i];
+	/*
+	** To get (wrong) behavior that's compatible with System V Release 2.0
+	** you'd replace the statement below with
+	**	t += ttisp->tt_gmtoff;
+	**	timesub(&t, 0L, sp, tmp);
+	*/
+	result = timesub(&t, ttisp->tt_gmtoff, sp, tmp);
+	if (result) {
+	  result->tm_isdst = ttisp->tt_isdst;
 #ifdef TM_ZONE
-    tmp->TM_ZONE = &sp->chars[ttisp->tt_abbrind];
+	  result->TM_ZONE = (char *) &sp->chars[ttisp->tt_abbrind];
 #endif /* defined TM_ZONE */
-    return result;
+	  if (setname)
+	    update_tzname_etc(sp, ttisp);
+	}
+	return result;
+}
+
+#if NETBSD_INSPIRED
+
+struct tm *
+localtime_rz(struct state *sp, time_t const *timep, struct tm *tmp)
+{
+  return localsub(sp, timep, 0, tmp);
+}
+
+#endif
+
+static struct tm *
+localtime_tzset(time_t const *timep, struct tm *tmp, bool setname)
+{
+  int err = lock();
+  if (err) {
+    errno = err;
+    return NULL;
+  }
+  if (setname || !lcl_is_set)
+    tzset_unlocked();
+  tmp = localsub(lclptr, timep, setname, tmp);
+  unlock();
+  return tmp;
 }
 
 struct tm *
-localtime(const time_t * const timep)
+localtime(const time_t *timep)
 {
-    return localtime_r(timep, &tmGlobal);
+  return localtime_tzset(timep, &tm, true);
 }
 
-/*
-** Re-entrant version of localtime.
-*/
-
 struct tm *
-localtime_r(const time_t * const timep, struct tm * tmp)
+localtime_r(const time_t *timep, struct tm *tmp)
 {
-    struct tm* result;
-
-    _tzLock();
-    tzset_locked();
-    result = localsub(timep, 0L, tmp, NULL); // android-changed: extra parameter.
-    _tzUnlock();
-
-    return result;
+  return localtime_tzset(timep, tmp, false);
 }
 
 /*
@@ -1409,37 +1543,22 @@
 */
 
 static struct tm *
-gmtsub(const time_t * const timep, const int_fast32_t offset,
-       struct tm *const tmp, struct state * sp __unused) // android-changed: added sp.
+gmtsub(struct state const *sp, time_t const *timep, int_fast32_t offset,
+       struct tm *tmp)
 {
-    register struct tm * result;
+	register struct tm *	result;
 
-    if (!gmt_is_set) {
-#ifdef ALL_STATE
-        gmtptr = malloc(sizeof *gmtptr);
-        gmt_is_set = gmtptr != NULL;
-#else
-        gmt_is_set = TRUE;
-#endif /* defined ALL_STATE */
-        if (gmt_is_set)
-            gmtload(gmtptr);
-    }
-    result = timesub(timep, offset, gmtptr, tmp);
+	result = timesub(timep, offset, gmtptr, tmp);
 #ifdef TM_ZONE
-    /*
-    ** Could get fancy here and deliver something such as
-    ** "UT+xxxx" or "UT-xxxx" if offset is non-zero,
-    ** but this is no time for a treasure hunt.
-    */
-    tmp->TM_ZONE = offset ? wildabbr : gmtptr ? gmtptr->chars : gmt;
+	/*
+	** Could get fancy here and deliver something such as
+	** "UT+xxxx" or "UT-xxxx" if offset is non-zero,
+	** but this is no time for a treasure hunt.
+	*/
+	tmp->TM_ZONE = ((char *)
+			(offset ? wildabbr : gmtptr ? gmtptr->chars : gmt));
 #endif /* defined TM_ZONE */
-    return result;
-}
-
-struct tm *
-gmtime(const time_t * const timep)
-{
-    return gmtime_r(timep, &tmGlobal);
+	return result;
 }
 
 /*
@@ -1447,23 +1566,25 @@
 */
 
 struct tm *
-gmtime_r(const time_t * const timep, struct tm * tmp)
+gmtime_r(const time_t *timep, struct tm *tmp)
 {
-    struct tm* result;
+  gmtcheck();
+  return gmtsub(gmtptr, timep, 0, tmp);
+}
 
-    _tzLock();
-    result = gmtsub(timep, 0L, tmp, NULL); // android-changed: extra parameter.
-    _tzUnlock();
-
-    return result;
+struct tm *
+gmtime(const time_t *timep)
+{
+  return gmtime_r(timep, &tm);
 }
 
 #ifdef STD_INSPIRED
 
 struct tm *
-offtime(const time_t *const timep, const long offset)
+offtime(const time_t *timep, long offset)
 {
-    return gmtsub(timep, offset, &tmGlobal, NULL); // android-changed: extra parameter.
+  gmtcheck();
+  return gmtsub(gmtptr, timep, offset, &tm);
 }
 
 #endif /* defined STD_INSPIRED */
@@ -1473,597 +1594,610 @@
 ** where, to make the math easy, the answer for year zero is defined as zero.
 */
 
-static int
+static int ATTRIBUTE_PURE
 leaps_thru_end_of(register const int y)
 {
-    return (y >= 0) ? (y / 4 - y / 100 + y / 400) :
-        -(leaps_thru_end_of(-(y + 1)) + 1);
+	return (y >= 0) ? (y / 4 - y / 100 + y / 400) :
+		-(leaps_thru_end_of(-(y + 1)) + 1);
 }
 
 static struct tm *
-timesub(const time_t *const timep, const int_fast32_t offset,
-        register const struct state *const sp,
-        register struct tm *const tmp)
+timesub(const time_t *timep, int_fast32_t offset,
+	const struct state *sp, struct tm *tmp)
 {
-    register const struct lsinfo * lp;
-    register time_t       tdays;
-    register int          idays;  /* unsigned would be so 2003 */
-    register int_fast64_t rem;
-    int                   y;
-    register const int *  ip;
-    register int_fast64_t corr;
-    register int          hit;
-    register int          i;
+	register const struct lsinfo *	lp;
+	register time_t			tdays;
+	register int			idays;	/* unsigned would be so 2003 */
+	register int_fast64_t		rem;
+	int				y;
+	register const int *		ip;
+	register int_fast64_t		corr;
+	register bool			hit;
+	register int			i;
 
-    corr = 0;
-    hit = 0;
-    i = (sp == NULL) ? 0 : sp->leapcnt;
-    while (--i >= 0) {
-        lp = &sp->lsis[i];
-        if (*timep >= lp->ls_trans) {
-            if (*timep == lp->ls_trans) {
-                hit = ((i == 0 && lp->ls_corr > 0) ||
-                    lp->ls_corr > sp->lsis[i - 1].ls_corr);
-                if (hit)
-                    while (i > 0 &&
-                        sp->lsis[i].ls_trans ==
-                        sp->lsis[i - 1].ls_trans + 1 &&
-                        sp->lsis[i].ls_corr ==
-                        sp->lsis[i - 1].ls_corr + 1) {
-                            ++hit;
-                            --i;
-                    }
-            }
-            corr = lp->ls_corr;
-            break;
-        }
-    }
-    y = EPOCH_YEAR;
-    tdays = *timep / SECSPERDAY;
-    rem = *timep - tdays * SECSPERDAY;
-    while (tdays < 0 || tdays >= year_lengths[isleap(y)]) {
-        int     newy;
-        register time_t tdelta;
-        register int    idelta;
-        register int    leapdays;
+	corr = 0;
+	hit = false;
+	i = (sp == NULL) ? 0 : sp->leapcnt;
+	while (--i >= 0) {
+		lp = &sp->lsis[i];
+		if (*timep >= lp->ls_trans) {
+			if (*timep == lp->ls_trans) {
+				hit = ((i == 0 && lp->ls_corr > 0) ||
+					lp->ls_corr > sp->lsis[i - 1].ls_corr);
+				if (hit)
+					while (i > 0 &&
+						sp->lsis[i].ls_trans ==
+						sp->lsis[i - 1].ls_trans + 1 &&
+						sp->lsis[i].ls_corr ==
+						sp->lsis[i - 1].ls_corr + 1) {
+							++hit;
+							--i;
+					}
+			}
+			corr = lp->ls_corr;
+			break;
+		}
+	}
+	y = EPOCH_YEAR;
+	tdays = *timep / SECSPERDAY;
+	rem = *timep % SECSPERDAY;
+	while (tdays < 0 || tdays >= year_lengths[isleap(y)]) {
+		int		newy;
+		register time_t	tdelta;
+		register int	idelta;
+		register int	leapdays;
 
-        tdelta = tdays / DAYSPERLYEAR;
-        if (! ((! TYPE_SIGNED(time_t) || INT_MIN <= tdelta)
-               && tdelta <= INT_MAX))
-                return NULL;
-        idelta = tdelta;
-        if (idelta == 0)
-            idelta = (tdays < 0) ? -1 : 1;
-        newy = y;
-        if (increment_overflow(&newy, idelta))
-            return NULL;
-        leapdays = leaps_thru_end_of(newy - 1) -
-            leaps_thru_end_of(y - 1);
-        tdays -= ((time_t) newy - y) * DAYSPERNYEAR;
-        tdays -= leapdays;
-        y = newy;
-    }
-    {
-        register int_fast32_t   seconds;
-
-        seconds = tdays * SECSPERDAY;
-        tdays = seconds / SECSPERDAY;
-        rem += seconds - tdays * SECSPERDAY;
-    }
-    /*
-    ** Given the range, we can now fearlessly cast...
-    */
-    idays = tdays;
-    rem += offset - corr;
-    while (rem < 0) {
-        rem += SECSPERDAY;
-        --idays;
-    }
-    while (rem >= SECSPERDAY) {
-        rem -= SECSPERDAY;
-        ++idays;
-    }
-    while (idays < 0) {
-        if (increment_overflow(&y, -1))
-            return NULL;
-        idays += year_lengths[isleap(y)];
-    }
-    while (idays >= year_lengths[isleap(y)]) {
-        idays -= year_lengths[isleap(y)];
-        if (increment_overflow(&y, 1))
-            return NULL;
-    }
-    tmp->tm_year = y;
-    if (increment_overflow(&tmp->tm_year, -TM_YEAR_BASE))
-        return NULL;
-    tmp->tm_yday = idays;
-    /*
-    ** The "extra" mods below avoid overflow problems.
-    */
-    tmp->tm_wday = EPOCH_WDAY +
-        ((y - EPOCH_YEAR) % DAYSPERWEEK) *
-        (DAYSPERNYEAR % DAYSPERWEEK) +
-        leaps_thru_end_of(y - 1) -
-        leaps_thru_end_of(EPOCH_YEAR - 1) +
-        idays;
-    tmp->tm_wday %= DAYSPERWEEK;
-    if (tmp->tm_wday < 0)
-        tmp->tm_wday += DAYSPERWEEK;
-    tmp->tm_hour = (int) (rem / SECSPERHOUR);
-    rem %= SECSPERHOUR;
-    tmp->tm_min = (int) (rem / SECSPERMIN);
-    /*
-    ** A positive leap second requires a special
-    ** representation. This uses "... ??:59:60" et seq.
-    */
-    tmp->tm_sec = (int) (rem % SECSPERMIN) + hit;
-    ip = mon_lengths[isleap(y)];
-    for (tmp->tm_mon = 0; idays >= ip[tmp->tm_mon]; ++(tmp->tm_mon))
-        idays -= ip[tmp->tm_mon];
-    tmp->tm_mday = (int) (idays + 1);
-    tmp->tm_isdst = 0;
+		tdelta = tdays / DAYSPERLYEAR;
+		if (! ((! TYPE_SIGNED(time_t) || INT_MIN <= tdelta)
+		       && tdelta <= INT_MAX))
+		  goto out_of_range;
+		idelta = tdelta;
+		if (idelta == 0)
+			idelta = (tdays < 0) ? -1 : 1;
+		newy = y;
+		if (increment_overflow(&newy, idelta))
+		  goto out_of_range;
+		leapdays = leaps_thru_end_of(newy - 1) -
+			leaps_thru_end_of(y - 1);
+		tdays -= ((time_t) newy - y) * DAYSPERNYEAR;
+		tdays -= leapdays;
+		y = newy;
+	}
+	/*
+	** Given the range, we can now fearlessly cast...
+	*/
+	idays = tdays;
+	rem += offset - corr;
+	while (rem < 0) {
+		rem += SECSPERDAY;
+		--idays;
+	}
+	while (rem >= SECSPERDAY) {
+		rem -= SECSPERDAY;
+		++idays;
+	}
+	while (idays < 0) {
+		if (increment_overflow(&y, -1))
+		  goto out_of_range;
+		idays += year_lengths[isleap(y)];
+	}
+	while (idays >= year_lengths[isleap(y)]) {
+		idays -= year_lengths[isleap(y)];
+		if (increment_overflow(&y, 1))
+		  goto out_of_range;
+	}
+	tmp->tm_year = y;
+	if (increment_overflow(&tmp->tm_year, -TM_YEAR_BASE))
+	  goto out_of_range;
+	tmp->tm_yday = idays;
+	/*
+	** The "extra" mods below avoid overflow problems.
+	*/
+	tmp->tm_wday = EPOCH_WDAY +
+		((y - EPOCH_YEAR) % DAYSPERWEEK) *
+		(DAYSPERNYEAR % DAYSPERWEEK) +
+		leaps_thru_end_of(y - 1) -
+		leaps_thru_end_of(EPOCH_YEAR - 1) +
+		idays;
+	tmp->tm_wday %= DAYSPERWEEK;
+	if (tmp->tm_wday < 0)
+		tmp->tm_wday += DAYSPERWEEK;
+	tmp->tm_hour = (int) (rem / SECSPERHOUR);
+	rem %= SECSPERHOUR;
+	tmp->tm_min = (int) (rem / SECSPERMIN);
+	/*
+	** A positive leap second requires a special
+	** representation. This uses "... ??:59:60" et seq.
+	*/
+	tmp->tm_sec = (int) (rem % SECSPERMIN) + hit;
+	ip = mon_lengths[isleap(y)];
+	for (tmp->tm_mon = 0; idays >= ip[tmp->tm_mon]; ++(tmp->tm_mon))
+		idays -= ip[tmp->tm_mon];
+	tmp->tm_mday = (int) (idays + 1);
+	tmp->tm_isdst = 0;
 #ifdef TM_GMTOFF
-    tmp->TM_GMTOFF = offset;
+	tmp->TM_GMTOFF = offset;
 #endif /* defined TM_GMTOFF */
-    return tmp;
+	return tmp;
+
+ out_of_range:
+	errno = EOVERFLOW;
+	return NULL;
 }
 
 char *
-ctime(const time_t * const timep)
+ctime(const time_t *timep)
 {
 /*
 ** Section 4.12.3.2 of X3.159-1989 requires that
-**  The ctime function converts the calendar time pointed to by timer
-**  to local time in the form of a string. It is equivalent to
-**      asctime(localtime(timer))
+**	The ctime function 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));
+  struct tm *tmp = localtime(timep);
+  return tmp ? asctime(tmp) : NULL;
 }
 
 char *
-ctime_r(const time_t * const timep, char * buf)
+ctime_r(const time_t *timep, char *buf)
 {
-    struct tm   mytm;
-
-    return asctime_r(localtime_r(timep, &mytm), buf);
+  struct tm mytm;
+  struct tm *tmp = localtime_r(timep, &mytm);
+  return tmp ? asctime_r(tmp, buf) : NULL;
 }
 
 /*
 ** 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.
-**  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).
+**	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.
+**	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).
 */
 
 #ifndef WRONG
-#define WRONG   (-1)
+#define WRONG	(-1)
 #endif /* !defined WRONG */
 
 /*
 ** Normalize logic courtesy Paul Eggert.
 */
 
-static int
-increment_overflow(int *const ip, int j)
+static bool
+increment_overflow(int *ip, int j)
 {
-    register int const i = *ip;
+	register int const	i = *ip;
 
-    /*
-    ** If i >= 0 there can only be overflow if i + j > INT_MAX
-    ** or if j > INT_MAX - i; given i >= 0, INT_MAX - i cannot overflow.
-    ** If i < 0 there can only be overflow if i + j < INT_MIN
-    ** or if j < INT_MIN - i; given i < 0, INT_MIN - i cannot overflow.
-    */
-    if ((i >= 0) ? (j > INT_MAX - i) : (j < INT_MIN - i))
-        return TRUE;
-    *ip += j;
-    return FALSE;
+	/*
+	** If i >= 0 there can only be overflow if i + j > INT_MAX
+	** or if j > INT_MAX - i; given i >= 0, INT_MAX - i cannot overflow.
+	** If i < 0 there can only be overflow if i + j < INT_MIN
+	** or if j < INT_MIN - i; given i < 0, INT_MIN - i cannot overflow.
+	*/
+	if ((i >= 0) ? (j > INT_MAX - i) : (j < INT_MIN - i))
+		return true;
+	*ip += j;
+	return false;
 }
 
-static int
+static bool
 increment_overflow32(int_fast32_t *const lp, int const m)
 {
-    register int_fast32_t const l = *lp;
+	register int_fast32_t const	l = *lp;
 
-    if ((l >= 0) ? (m > INT_FAST32_MAX - l) : (m < INT_FAST32_MIN - l))
-        return TRUE;
-    *lp += m;
-    return FALSE;
+	if ((l >= 0) ? (m > INT_FAST32_MAX - l) : (m < INT_FAST32_MIN - l))
+		return true;
+	*lp += m;
+	return false;
 }
 
-static int
+static bool
 increment_overflow_time(time_t *tp, int_fast32_t j)
 {
-    /*
-    ** This is like
-    ** 'if (! (time_t_min <= *tp + j && *tp + j <= time_t_max)) ...',
-    ** except that it does the right thing even if *tp + j would overflow.
-    */
-    if (! (j < 0
-           ? (TYPE_SIGNED(time_t) ? time_t_min - j <= *tp : -1 - j < *tp)
-           : *tp <= time_t_max - j))
-        return TRUE;
-    *tp += j;
-    return FALSE;
+	/*
+	** This is like
+	** 'if (! (time_t_min <= *tp + j && *tp + j <= time_t_max)) ...',
+	** except that it does the right thing even if *tp + j would overflow.
+	*/
+	if (! (j < 0
+	       ? (TYPE_SIGNED(time_t) ? time_t_min - j <= *tp : -1 - j < *tp)
+	       : *tp <= time_t_max - j))
+		return true;
+	*tp += j;
+	return false;
 }
 
-static int
+static bool
 normalize_overflow(int *const tensptr, int *const unitsptr, const int base)
 {
-    register int tensdelta;
+	register int	tensdelta;
 
-    tensdelta = (*unitsptr >= 0) ?
-        (*unitsptr / base) :
-        (-1 - (-1 - *unitsptr) / base);
-    *unitsptr -= tensdelta * base;
-    return increment_overflow(tensptr, tensdelta);
+	tensdelta = (*unitsptr >= 0) ?
+		(*unitsptr / base) :
+		(-1 - (-1 - *unitsptr) / base);
+	*unitsptr -= tensdelta * base;
+	return increment_overflow(tensptr, tensdelta);
+}
+
+static bool
+normalize_overflow32(int_fast32_t *tensptr, int *unitsptr, int base)
+{
+	register int	tensdelta;
+
+	tensdelta = (*unitsptr >= 0) ?
+		(*unitsptr / base) :
+		(-1 - (-1 - *unitsptr) / base);
+	*unitsptr -= tensdelta * base;
+	return increment_overflow32(tensptr, tensdelta);
 }
 
 static int
-normalize_overflow32(int_fast32_t *const tensptr, int *const unitsptr,
-             const int base)
+tmcomp(register const struct tm *const atmp,
+       register const struct tm *const btmp)
 {
-    register int tensdelta;
+	register int	result;
 
-    tensdelta = (*unitsptr >= 0) ?
-        (*unitsptr / base) :
-        (-1 - (-1 - *unitsptr) / base);
-    *unitsptr -= tensdelta * base;
-    return increment_overflow32(tensptr, tensdelta);
-}
-
-static int
-tmcomp(register const struct tm * const atmp,
-       register const struct tm * const btmp)
-{
-    register int result;
-
-    if (atmp->tm_year != btmp->tm_year)
-        return atmp->tm_year < btmp->tm_year ? -1 : 1;
-    if ((result = (atmp->tm_mon - btmp->tm_mon)) == 0 &&
-        (result = (atmp->tm_mday - btmp->tm_mday)) == 0 &&
-        (result = (atmp->tm_hour - btmp->tm_hour)) == 0 &&
-        (result = (atmp->tm_min - btmp->tm_min)) == 0)
-            result = atmp->tm_sec - btmp->tm_sec;
-    return result;
+	if (atmp->tm_year != btmp->tm_year)
+		return atmp->tm_year < btmp->tm_year ? -1 : 1;
+	if ((result = (atmp->tm_mon - btmp->tm_mon)) == 0 &&
+		(result = (atmp->tm_mday - btmp->tm_mday)) == 0 &&
+		(result = (atmp->tm_hour - btmp->tm_hour)) == 0 &&
+		(result = (atmp->tm_min - btmp->tm_min)) == 0)
+			result = atmp->tm_sec - btmp->tm_sec;
+	return result;
 }
 
 static time_t
-time2sub(struct tm * const tmp,
-         struct tm *(*const funcp)(const time_t*, int_fast32_t, struct tm*, struct state*),
-         const int_fast32_t offset,
-         int * const okayp,
-         const int do_norm_secs, struct state * sp) // android-changed: added sp
+time2sub(struct tm *const tmp,
+	 struct tm *(*funcp)(struct state const *, time_t const *,
+			     int_fast32_t, struct tm *),
+	 struct state const *sp,
+	 const int_fast32_t offset,
+	 bool *okayp,
+	 bool do_norm_secs)
 {
-    register int          dir;
-    register int          i, j;
-    register int          saved_seconds;
-    register int_fast32_t li;
-    register time_t       lo;
-    register time_t       hi;
-    int_fast32_t          y;
-    time_t                newt;
-    time_t                t;
-    struct tm             yourtm, mytm;
+	register int			dir;
+	register int			i, j;
+	register int			saved_seconds;
+	register int_fast32_t		li;
+	register time_t			lo;
+	register time_t			hi;
+	int_fast32_t			y;
+	time_t				newt;
+	time_t				t;
+	struct tm			yourtm, mytm;
 
-    *okayp = FALSE;
-    yourtm = *tmp;
-    if (do_norm_secs) {
-        if (normalize_overflow(&yourtm.tm_min, &yourtm.tm_sec,
-            SECSPERMIN))
-                return WRONG;
-    }
-    if (normalize_overflow(&yourtm.tm_hour, &yourtm.tm_min, MINSPERHOUR))
-        return WRONG;
-    if (normalize_overflow(&yourtm.tm_mday, &yourtm.tm_hour, HOURSPERDAY))
-        return WRONG;
-    y = yourtm.tm_year;
-    if (normalize_overflow32(&y, &yourtm.tm_mon, MONSPERYEAR))
-        return WRONG;
-    /*
-    ** Turn y into an actual year number for now.
-    ** It is converted back to an offset from TM_YEAR_BASE later.
-    */
-    if (increment_overflow32(&y, TM_YEAR_BASE))
-        return WRONG;
-    while (yourtm.tm_mday <= 0) {
-        if (increment_overflow32(&y, -1))
-            return WRONG;
-        li = y + (1 < yourtm.tm_mon);
-        yourtm.tm_mday += year_lengths[isleap(li)];
-    }
-    while (yourtm.tm_mday > DAYSPERLYEAR) {
-        li = y + (1 < yourtm.tm_mon);
-        yourtm.tm_mday -= year_lengths[isleap(li)];
-        if (increment_overflow32(&y, 1))
-            return WRONG;
-    }
-    for ( ; ; ) {
-        i = mon_lengths[isleap(y)][yourtm.tm_mon];
-        if (yourtm.tm_mday <= i)
-            break;
-        yourtm.tm_mday -= i;
-        if (++yourtm.tm_mon >= MONSPERYEAR) {
-            yourtm.tm_mon = 0;
-            if (increment_overflow32(&y, 1))
-                return WRONG;
-        }
-    }
-    if (increment_overflow32(&y, -TM_YEAR_BASE))
-        return WRONG;
-    yourtm.tm_year = y;
-    if (yourtm.tm_year != y)
-        return WRONG;
-    if (yourtm.tm_sec >= 0 && yourtm.tm_sec < SECSPERMIN)
-        saved_seconds = 0;
-    else if (y + TM_YEAR_BASE < EPOCH_YEAR) {
-        /*
-        ** We can't set tm_sec to 0, because that might push the
-        ** time below the minimum representable time.
-        ** Set tm_sec to 59 instead.
-        ** This assumes that the minimum representable time is
-        ** not in the same minute that a leap second was deleted from,
-        ** which is a safer assumption than using 58 would be.
-        */
-        if (increment_overflow(&yourtm.tm_sec, 1 - SECSPERMIN))
-            return WRONG;
-        saved_seconds = yourtm.tm_sec;
-        yourtm.tm_sec = SECSPERMIN - 1;
-    } else {
-        saved_seconds = yourtm.tm_sec;
-        yourtm.tm_sec = 0;
-    }
-    /*
-    ** Do a binary search (this works whatever time_t's type is).
-    */
-    if (!TYPE_SIGNED(time_t)) {
-        lo = 0;
-        hi = lo - 1;
-    } else {
-        lo = 1;
-        for (i = 0; i < (int) TYPE_BIT(time_t) - 1; ++i)
-            lo *= 2;
-        hi = -(lo + 1);
-    }
-    for ( ; ; ) {
-        t = lo / 2 + hi / 2;
-        if (t < lo)
-            t = lo;
-        else if (t > hi)
-            t = hi;
-        if ((*funcp)(&t, offset, &mytm, sp) == NULL) { // android-changed: added sp.
-            /*
-            ** Assume that t is too extreme to be represented in
-            ** a struct tm; arrange things so that it is less
-            ** extreme on the next pass.
-            */
-            dir = (t > 0) ? 1 : -1;
-        } else  dir = tmcomp(&mytm, &yourtm);
-        if (dir != 0) {
-            if (t == lo) {
-                if (t == time_t_max)
-                    return WRONG;
-                ++t;
-                ++lo;
-            } else if (t == hi) {
-                if (t == time_t_min)
-                    return WRONG;
-                --t;
-                --hi;
-            }
-            if (lo > hi)
-                return WRONG;
-            if (dir > 0)
-                hi = t;
-            else    lo = t;
-            continue;
-        }
-        if (yourtm.tm_isdst < 0 || mytm.tm_isdst == yourtm.tm_isdst)
-            break;
-        /*
-        ** Right time, wrong type.
-        ** Hunt for right time, right type.
-        ** It's okay to guess wrong since the guess
-        ** gets checked.
-        */
-        // BEGIN android-changed: support user-supplied sp
-        if (sp == NULL) {
-            sp = (struct state *)
-                ((funcp == localsub) ? lclptr : gmtptr);
-        }
-        // END android-changed
-        if (sp == NULL)
-            return WRONG;
-        for (i = sp->typecnt - 1; i >= 0; --i) {
-            if (sp->ttis[i].tt_isdst != yourtm.tm_isdst)
-                continue;
-            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 -
-                    sp->ttis[i].tt_gmtoff;
-                if ((*funcp)(&newt, offset, &mytm, sp) == NULL) // android-changed: added sp.
-                    continue;
-                if (tmcomp(&mytm, &yourtm) != 0)
-                    continue;
-                if (mytm.tm_isdst != yourtm.tm_isdst)
-                    continue;
-                /*
-                ** We have a match.
-                */
-                t = newt;
-                goto label;
-            }
-        }
-        return WRONG;
-    }
+	*okayp = false;
+	yourtm = *tmp;
+	if (do_norm_secs) {
+		if (normalize_overflow(&yourtm.tm_min, &yourtm.tm_sec,
+			SECSPERMIN))
+				return WRONG;
+	}
+	if (normalize_overflow(&yourtm.tm_hour, &yourtm.tm_min, MINSPERHOUR))
+		return WRONG;
+	if (normalize_overflow(&yourtm.tm_mday, &yourtm.tm_hour, HOURSPERDAY))
+		return WRONG;
+	y = yourtm.tm_year;
+	if (normalize_overflow32(&y, &yourtm.tm_mon, MONSPERYEAR))
+		return WRONG;
+	/*
+	** Turn y into an actual year number for now.
+	** It is converted back to an offset from TM_YEAR_BASE later.
+	*/
+	if (increment_overflow32(&y, TM_YEAR_BASE))
+		return WRONG;
+	while (yourtm.tm_mday <= 0) {
+		if (increment_overflow32(&y, -1))
+			return WRONG;
+		li = y + (1 < yourtm.tm_mon);
+		yourtm.tm_mday += year_lengths[isleap(li)];
+	}
+	while (yourtm.tm_mday > DAYSPERLYEAR) {
+		li = y + (1 < yourtm.tm_mon);
+		yourtm.tm_mday -= year_lengths[isleap(li)];
+		if (increment_overflow32(&y, 1))
+			return WRONG;
+	}
+	for ( ; ; ) {
+		i = mon_lengths[isleap(y)][yourtm.tm_mon];
+		if (yourtm.tm_mday <= i)
+			break;
+		yourtm.tm_mday -= i;
+		if (++yourtm.tm_mon >= MONSPERYEAR) {
+			yourtm.tm_mon = 0;
+			if (increment_overflow32(&y, 1))
+				return WRONG;
+		}
+	}
+	if (increment_overflow32(&y, -TM_YEAR_BASE))
+		return WRONG;
+	if (! (INT_MIN <= y && y <= INT_MAX))
+		return WRONG;
+	yourtm.tm_year = y;
+	if (yourtm.tm_sec >= 0 && yourtm.tm_sec < SECSPERMIN)
+		saved_seconds = 0;
+	else if (y + TM_YEAR_BASE < EPOCH_YEAR) {
+		/*
+		** We can't set tm_sec to 0, because that might push the
+		** time below the minimum representable time.
+		** Set tm_sec to 59 instead.
+		** This assumes that the minimum representable time is
+		** not in the same minute that a leap second was deleted from,
+		** which is a safer assumption than using 58 would be.
+		*/
+		if (increment_overflow(&yourtm.tm_sec, 1 - SECSPERMIN))
+			return WRONG;
+		saved_seconds = yourtm.tm_sec;
+		yourtm.tm_sec = SECSPERMIN - 1;
+	} else {
+		saved_seconds = yourtm.tm_sec;
+		yourtm.tm_sec = 0;
+	}
+	/*
+	** Do a binary search (this works whatever time_t's type is).
+	*/
+	lo = time_t_min;
+	hi = time_t_max;
+	for ( ; ; ) {
+		t = lo / 2 + hi / 2;
+		if (t < lo)
+			t = lo;
+		else if (t > hi)
+			t = hi;
+		if (! funcp(sp, &t, offset, &mytm)) {
+			/*
+			** Assume that t is too extreme to be represented in
+			** a struct tm; arrange things so that it is less
+			** extreme on the next pass.
+			*/
+			dir = (t > 0) ? 1 : -1;
+		} else	dir = tmcomp(&mytm, &yourtm);
+		if (dir != 0) {
+			if (t == lo) {
+				if (t == time_t_max)
+					return WRONG;
+				++t;
+				++lo;
+			} else if (t == hi) {
+				if (t == time_t_min)
+					return WRONG;
+				--t;
+				--hi;
+			}
+			if (lo > hi)
+				return WRONG;
+			if (dir > 0)
+				hi = t;
+			else	lo = t;
+			continue;
+		}
+#if defined TM_GMTOFF && ! UNINIT_TRAP
+		if (mytm.TM_GMTOFF != yourtm.TM_GMTOFF
+		    && (yourtm.TM_GMTOFF < 0
+			? (-SECSPERDAY <= yourtm.TM_GMTOFF
+			   && (mytm.TM_GMTOFF <=
+			       (SMALLEST (INT_FAST32_MAX, LONG_MAX)
+				+ yourtm.TM_GMTOFF)))
+			: (yourtm.TM_GMTOFF <= SECSPERDAY
+			   && ((BIGGEST (INT_FAST32_MIN, LONG_MIN)
+				+ yourtm.TM_GMTOFF)
+			       <= mytm.TM_GMTOFF)))) {
+		  /* MYTM matches YOURTM except with the wrong UTC offset.
+		     YOURTM.TM_GMTOFF is plausible, so try it instead.
+		     It's OK if YOURTM.TM_GMTOFF contains uninitialized data,
+		     since the guess gets checked.  */
+		  time_t altt = t;
+		  int_fast32_t diff = mytm.TM_GMTOFF - yourtm.TM_GMTOFF;
+		  if (!increment_overflow_time(&altt, diff)) {
+		    struct tm alttm;
+		    if (funcp(sp, &altt, offset, &alttm)
+			&& alttm.tm_isdst == mytm.tm_isdst
+			&& alttm.TM_GMTOFF == yourtm.TM_GMTOFF
+			&& tmcomp(&alttm, &yourtm) == 0) {
+		      t = altt;
+		      mytm = alttm;
+		    }
+		  }
+		}
+#endif
+		if (yourtm.tm_isdst < 0 || mytm.tm_isdst == yourtm.tm_isdst)
+			break;
+		/*
+		** Right time, wrong type.
+		** Hunt for right time, right type.
+		** It's okay to guess wrong since the guess
+		** gets checked.
+		*/
+		if (sp == NULL)
+			return WRONG;
+		for (i = sp->typecnt - 1; i >= 0; --i) {
+			if (sp->ttis[i].tt_isdst != yourtm.tm_isdst)
+				continue;
+			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 -
+					sp->ttis[i].tt_gmtoff;
+				if (! funcp(sp, &newt, offset, &mytm))
+					continue;
+				if (tmcomp(&mytm, &yourtm) != 0)
+					continue;
+				if (mytm.tm_isdst != yourtm.tm_isdst)
+					continue;
+				/*
+				** We have a match.
+				*/
+				t = newt;
+				goto label;
+			}
+		}
+		return WRONG;
+	}
 label:
-    newt = t + saved_seconds;
-    if ((newt < t) != (saved_seconds < 0))
-        return WRONG;
-    t = newt;
-    if ((*funcp)(&t, offset, tmp, sp)) // android-changed: added sp.
-        *okayp = TRUE;
-    return t;
+	newt = t + saved_seconds;
+	if ((newt < t) != (saved_seconds < 0))
+		return WRONG;
+	t = newt;
+	if (funcp(sp, &t, offset, tmp))
+		*okayp = true;
+	return t;
 }
 
 static time_t
-time2(struct tm * const tmp,
-      struct tm * (*const funcp)(const time_t *, int_fast32_t, struct tm *, struct state *), // android-changed: added sp.
+time2(struct tm * const	tmp,
+      struct tm *(*funcp)(struct state const *, time_t const *,
+			  int_fast32_t, struct tm *),
+      struct state const *sp,
       const int_fast32_t offset,
-      int *const okayp, struct state* sp) // android-changed: added sp.
+      bool *okayp)
 {
-    time_t t;
+	time_t	t;
 
-    /*
-    ** First try without normalization of seconds
-    ** (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, sp);
-    return *okayp ? t : time2sub(tmp, funcp, offset, okayp, TRUE, sp);
+	/*
+	** First try without normalization of seconds
+	** (in case tm_sec contains a value associated with a leap second).
+	** If that fails, try with normalization of seconds.
+	*/
+	t = time2sub(tmp, funcp, sp, offset, okayp, false);
+	return *okayp ? t : time2sub(tmp, funcp, sp, offset, okayp, true);
 }
 
 static time_t
-time1(struct tm * const tmp,
-      struct tm * (* const funcp) (const time_t *, int_fast32_t, struct tm *, struct state *), // android-changed: added sp.
-      const int_fast32_t offset, struct state * sp) // android-changed: added sp.
+time1(struct tm *const tmp,
+      struct tm *(*funcp) (struct state const *, time_t const *,
+			   int_fast32_t, struct tm *),
+      struct state const *sp,
+      const int_fast32_t offset)
 {
-    register time_t t;
-    register int    samei, otheri;
-    register int    sameind, otherind;
-    register int    i;
-    register int    nseen;
-    char            seen[TZ_MAX_TYPES];
-    unsigned char   types[TZ_MAX_TYPES];
-    int             okay;
+	register time_t			t;
+	register int			samei, otheri;
+	register int			sameind, otherind;
+	register int			i;
+	register int			nseen;
+	char				seen[TZ_MAX_TYPES];
+	unsigned char			types[TZ_MAX_TYPES];
+	bool				okay;
 
-    if (tmp == NULL) {
-        errno = EINVAL;
-        return WRONG;
-    }
-    if (tmp->tm_isdst > 1)
-        tmp->tm_isdst = 1;
-    t = time2(tmp, funcp, offset, &okay, sp); // android-changed: added sp.
-    if (okay)
-        return t;
-    if (tmp->tm_isdst < 0)
+	if (tmp == NULL) {
+		errno = EINVAL;
+		return WRONG;
+	}
+	if (tmp->tm_isdst > 1)
+		tmp->tm_isdst = 1;
+	t = time2(tmp, funcp, sp, offset, &okay);
+	if (okay)
+		return t;
+	if (tmp->tm_isdst < 0)
 #ifdef PCTS
-        /*
-        ** POSIX Conformance Test Suite code courtesy Grant Sullivan.
-        */
-        tmp->tm_isdst = 0;  /* reset to std and try again */
+		/*
+		** POSIX Conformance Test Suite code courtesy Grant Sullivan.
+		*/
+		tmp->tm_isdst = 0;	/* reset to std and try again */
 #else
-        return t;
+		return t;
 #endif /* !defined PCTS */
-    /*
-    ** We're supposed to assume that somebody took a time of one type
-    ** and did some math on it that yielded a "struct tm" that's bad.
-    ** We try to divine the type they started from and adjust to the
-    ** type they need.
-    */
-    // BEGIN android-changed: support user-supplied sp.
-    if (sp == NULL) {
-        sp = (struct state *) ((funcp == localsub) ?  lclptr : gmtptr);
-    }
-    // BEGIN android-changed
-    if (sp == NULL)
-        return WRONG;
-    for (i = 0; i < sp->typecnt; ++i)
-        seen[i] = FALSE;
-    nseen = 0;
-    for (i = sp->timecnt - 1; i >= 0; --i)
-        if (!seen[sp->types[i]]) {
-            seen[sp->types[i]] = TRUE;
-            types[nseen++] = sp->types[i];
-        }
-    for (sameind = 0; sameind < nseen; ++sameind) {
-        samei = types[sameind];
-        if (sp->ttis[samei].tt_isdst != tmp->tm_isdst)
-            continue;
-        for (otherind = 0; otherind < nseen; ++otherind) {
-            otheri = types[otherind];
-            if (sp->ttis[otheri].tt_isdst == tmp->tm_isdst)
-                continue;
-            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, sp); // android-changed: added sp.
-            if (okay)
-                return t;
-            tmp->tm_sec -= sp->ttis[otheri].tt_gmtoff -
-                    sp->ttis[samei].tt_gmtoff;
-            tmp->tm_isdst = !tmp->tm_isdst;
-        }
-    }
-    return WRONG;
+	/*
+	** We're supposed to assume that somebody took a time of one type
+	** and did some math on it that yielded a "struct tm" that's bad.
+	** We try to divine the type they started from and adjust to the
+	** type they need.
+	*/
+	if (sp == NULL)
+		return WRONG;
+	for (i = 0; i < sp->typecnt; ++i)
+		seen[i] = false;
+	nseen = 0;
+	for (i = sp->timecnt - 1; i >= 0; --i)
+		if (!seen[sp->types[i]]) {
+			seen[sp->types[i]] = true;
+			types[nseen++] = sp->types[i];
+		}
+	for (sameind = 0; sameind < nseen; ++sameind) {
+		samei = types[sameind];
+		if (sp->ttis[samei].tt_isdst != tmp->tm_isdst)
+			continue;
+		for (otherind = 0; otherind < nseen; ++otherind) {
+			otheri = types[otherind];
+			if (sp->ttis[otheri].tt_isdst == tmp->tm_isdst)
+				continue;
+			tmp->tm_sec += sp->ttis[otheri].tt_gmtoff -
+					sp->ttis[samei].tt_gmtoff;
+			tmp->tm_isdst = !tmp->tm_isdst;
+			t = time2(tmp, funcp, sp, offset, &okay);
+			if (okay)
+				return t;
+			tmp->tm_sec -= sp->ttis[otheri].tt_gmtoff -
+					sp->ttis[samei].tt_gmtoff;
+			tmp->tm_isdst = !tmp->tm_isdst;
+		}
+	}
+	return WRONG;
 }
 
+static time_t
+mktime_tzname(struct state *sp, struct tm *tmp, bool setname)
+{
+  if (sp)
+    return time1(tmp, localsub, sp, setname);
+  else {
+    gmtcheck();
+    return time1(tmp, gmtsub, gmtptr, 0);
+  }
+}
+
+#if NETBSD_INSPIRED
+
 time_t
-mktime(struct tm * const tmp)
+mktime_z(struct state *sp, struct tm *tmp)
 {
-    _tzLock();
-    tzset_locked();
-    time_t result = time1(tmp, localsub, 0L, NULL); // android-changed: extra parameter.
-    _tzUnlock();
-    return result;
+  return mktime_tzname(sp, tmp, false);
+}
+
+#endif
+
+time_t
+mktime(struct tm *tmp)
+{
+  time_t t;
+  int err = lock();
+  if (err) {
+    errno = err;
+    return -1;
+  }
+  tzset_unlocked();
+  t = mktime_tzname(lclptr, tmp, true);
+  unlock();
+  return t;
 }
 
 #ifdef STD_INSPIRED
 
 time_t
-timelocal(struct tm * const tmp)
+timelocal(struct tm *tmp)
 {
-    if (tmp != NULL)
-        tmp->tm_isdst = -1; /* in case it wasn't initialized */
-    return mktime(tmp);
+	if (tmp != NULL)
+		tmp->tm_isdst = -1;	/* in case it wasn't initialized */
+	return mktime(tmp);
 }
 
 time_t
-timegm(struct tm * const tmp)
+timegm(struct tm *tmp)
 {
-    time_t result;
-
-    if (tmp != NULL)
-        tmp->tm_isdst = 0;
-    _tzLock();
-    result = time1(tmp, gmtsub, 0L, NULL); // android-changed: extra parameter.
-    _tzUnlock();
-
-    return result;
+  return timeoff(tmp, 0);
 }
 
 time_t
-timeoff(struct tm *const tmp, const long offset)
+timeoff(struct tm *tmp, long offset)
 {
-    if (tmp != NULL)
-        tmp->tm_isdst = 0;
-    return time1(tmp, gmtsub, offset, NULL); // android-changed: extra parameter.
+  if (tmp)
+    tmp->tm_isdst = 0;
+  gmtcheck();
+  return time1(tmp, gmtsub, gmtptr, offset);
 }
 
 #endif /* defined STD_INSPIRED */
 
-#ifdef CMUCS
-
-/*
-** The following is supplied for compatibility with
-** previous versions of the CMUCS runtime library.
-*/
-
-long
-gtime(struct tm * const tmp)
-{
-    const time_t t = mktime(tmp);
-
-    if (t == WRONG)
-        return -1;
-    return t;
-}
-
-#endif /* defined CMUCS */
-
 /*
 ** XXX--is the below the right way to conditionalize??
 */
@@ -2079,64 +2213,105 @@
 */
 
 static int_fast64_t
-leapcorr(time_t * timep)
+leapcorr(struct state const *sp, time_t t)
 {
-    register struct state *  sp;
-    register struct lsinfo * lp;
-    register int             i;
+	register struct lsinfo const *	lp;
+	register int			i;
 
-    sp = lclptr;
-    i = sp->leapcnt;
-    while (--i >= 0) {
-        lp = &sp->lsis[i];
-        if (*timep >= lp->ls_trans)
-            return lp->ls_corr;
-    }
-    return 0;
+	i = sp->leapcnt;
+	while (--i >= 0) {
+		lp = &sp->lsis[i];
+		if (t >= lp->ls_trans)
+			return lp->ls_corr;
+	}
+	return 0;
+}
+
+NETBSD_INSPIRED_EXTERN time_t ATTRIBUTE_PURE
+time2posix_z(struct state *sp, time_t t)
+{
+  return t - leapcorr(sp, t);
 }
 
 time_t
 time2posix(time_t t)
 {
-    tzset();
-    return t - leapcorr(&t);
+  int err = lock();
+  if (err) {
+    errno = err;
+    return -1;
+  }
+  if (!lcl_is_set)
+    tzset_unlocked();
+  if (lclptr)
+    t = time2posix_z(lclptr, t);
+  unlock();
+  return t;
+}
+
+NETBSD_INSPIRED_EXTERN time_t ATTRIBUTE_PURE
+posix2time_z(struct state *sp, time_t t)
+{
+	time_t	x;
+	time_t	y;
+	/*
+	** 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(sp, t);
+	y = x - leapcorr(sp, x);
+	if (y < t) {
+		do {
+			x++;
+			y = x - leapcorr(sp, x);
+		} while (y < t);
+		x -= y != t;
+	} else if (y > t) {
+		do {
+			--x;
+			y = x - leapcorr(sp, x);
+		} while (y > t);
+		x += y != t;
+	}
+	return x;
 }
 
 time_t
 posix2time(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
-    ** hit, the corresponding time doesn't exist,
-    ** so we return an adjacent second.
-    */
-    x = t + leapcorr(&t);
-    y = x - leapcorr(&x);
-    if (y < t) {
-        do {
-            x++;
-            y = x - leapcorr(&x);
-        } while (y < t);
-        if (t != y)
-            return x - 1;
-    } else if (y > t) {
-        do {
-            --x;
-            y = x - leapcorr(&x);
-        } while (y > t);
-        if (t != y)
-            return x + 1;
-    }
-    return x;
+  int err = lock();
+  if (err) {
+    errno = err;
+    return -1;
+  }
+  if (!lcl_is_set)
+    tzset_unlocked();
+  if (lclptr)
+    t = posix2time_z(lclptr, t);
+  unlock();
+  return t;
 }
 
 #endif /* defined STD_INSPIRED */
 
+#ifdef time_tz
+
+/* Convert from the underlying system's time_t to the ersatz time_tz,
+   which is called 'time_t' in this file.  */
+
+time_t
+time(time_t *p)
+{
+  time_t r = sys_time(0);
+  if (p)
+    *p = r;
+  return r;
+}
+
+#endif
+
 // BEGIN android-added
 
 #include <assert.h>
@@ -2144,7 +2319,7 @@
 #include <arpa/inet.h> // For ntohl(3).
 
 static int __bionic_open_tzdata_path(const char* path_prefix_variable, const char* path_suffix,
-                                     const char* olson_id, int* data_size) {
+                                     const char* olson_id) {
   const char* path_prefix = getenv(path_prefix_variable);
   if (path_prefix == NULL) {
     fprintf(stderr, "%s: %s not set!\n", __FUNCTION__, path_prefix_variable);
@@ -2159,7 +2334,6 @@
   snprintf(path, path_length, "%s/%s", path_prefix, path_suffix);
   int fd = TEMP_FAILURE_RETRY(open(path, OPEN_MODE));
   if (fd == -1) {
-    XLOG(("%s: could not open \"%s\": %s\n", __FUNCTION__, path, strerror(errno)));
     free(path);
     return -2; // Distinguish failure to find any data from failure to find a specific id.
   }
@@ -2243,7 +2417,6 @@
 
     if (strcmp(this_id, olson_id) == 0) {
       specific_zone_offset = ntohl(entry->start) + ntohl(header.data_offset);
-      *data_size = ntohl(entry->length);
       break;
     }
 
@@ -2252,7 +2425,6 @@
   free(index);
 
   if (specific_zone_offset == -1) {
-    XLOG(("%s: couldn't find zone \"%s\"\n", __FUNCTION__, olson_id));
     free(path);
     close(fd);
     return -1;
@@ -2272,10 +2444,10 @@
   return fd;
 }
 
-static int __bionic_open_tzdata(const char* olson_id, int* data_size) {
-  int fd = __bionic_open_tzdata_path("ANDROID_DATA", "/misc/zoneinfo/current/tzdata", olson_id, data_size);
+static int __bionic_open_tzdata(const char* olson_id) {
+  int fd = __bionic_open_tzdata_path("ANDROID_DATA", "/misc/zoneinfo/current/tzdata", olson_id);
   if (fd < 0) {
-    fd = __bionic_open_tzdata_path("ANDROID_ROOT", "/usr/share/zoneinfo/tzdata", olson_id, data_size);
+    fd = __bionic_open_tzdata_path("ANDROID_ROOT", "/usr/share/zoneinfo/tzdata", olson_id);
     if (fd == -2) {
       // The first thing that 'recovery' does is try to format the current time. It doesn't have
       // any tzdata available, so we must not abort here --- doing so breaks the recovery image!
@@ -2287,7 +2459,7 @@
 
 // Caches the most recent timezone (http://b/8270865).
 static int __bionic_tzload_cached(const char* name, struct state* const sp, const int doextend) {
-  _tzLock();
+  lock();
 
   // Our single-item cache.
   static char* g_cached_time_zone_name;
@@ -2296,7 +2468,7 @@
   // Do we already have this timezone cached?
   if (g_cached_time_zone_name != NULL && strcmp(name, g_cached_time_zone_name) == 0) {
     *sp = g_cached_time_zone;
-    _tzUnlock();
+    unlock();
     return 0;
   }
 
@@ -2309,7 +2481,7 @@
     g_cached_time_zone = *sp;
   }
 
-  _tzUnlock();
+  unlock();
   return rc;
 }
 
@@ -2321,12 +2493,12 @@
 
   if (st == NULL)
     return 0;
-  if (__bionic_tzload_cached(tz, st, TRUE) != 0) {
+  if (__bionic_tzload_cached(tz, st, true) != 0) {
     // TODO: not sure what's best here, but for now, we fall back to gmt.
     gmtload(st);
   }
 
-  return_value = time1(tmp, localsub, 0L, st);
+  return_value = time1(tmp, localsub, st, 0L);
   free(st);
   return return_value;
 }
diff --git a/libc/tzcode/private.h b/libc/tzcode/private.h
index 494e142..1c176e6 100644
--- a/libc/tzcode/private.h
+++ b/libc/tzcode/private.h
@@ -19,13 +19,9 @@
 
 /*
 ** Defaults for preprocessor symbols.
-** You can override these in your C compiler options, e.g. '-DHAVE_ADJTIME=0'.
+** You can override these in your C compiler options, e.g. '-DHAVE_GETTEXT=1'.
 */
 
-#ifndef HAVE_ADJTIME
-#define HAVE_ADJTIME		1
-#endif /* !defined HAVE_ADJTIME */
-
 #ifndef HAVE_GETTEXT
 #define HAVE_GETTEXT		0
 #endif /* !defined HAVE_GETTEXT */
@@ -38,9 +34,9 @@
 #define HAVE_LINK		1
 #endif /* !defined HAVE_LINK */
 
-#ifndef HAVE_SETTIMEOFDAY
-#define HAVE_SETTIMEOFDAY	3
-#endif /* !defined HAVE_SETTIMEOFDAY */
+#ifndef HAVE_STRDUP
+#define HAVE_STRDUP 1
+#endif
 
 #ifndef HAVE_SYMLINK
 #define HAVE_SYMLINK		1
@@ -59,32 +55,61 @@
 #endif /* !defined HAVE_UNISTD_H */
 
 #ifndef HAVE_UTMPX_H
-#define HAVE_UTMPX_H		0
+#define HAVE_UTMPX_H		1
 #endif /* !defined HAVE_UTMPX_H */
 
-#if !defined(__ANDROID__)
-#ifndef LOCALE_HOME
-#define LOCALE_HOME		"/usr/lib/locale"
-#endif /* !defined LOCALE_HOME */
-#endif // __ANDROID__
+#ifndef NETBSD_INSPIRED
+# define NETBSD_INSPIRED 1
+#endif
 
 #if HAVE_INCOMPATIBLE_CTIME_R
 #define asctime_r _incompatible_asctime_r
 #define ctime_r _incompatible_ctime_r
 #endif /* HAVE_INCOMPATIBLE_CTIME_R */
 
+/* Enable tm_gmtoff and tm_zone on GNUish systems.  */
+#define _GNU_SOURCE 1
+/* Fix asctime_r on Solaris 10.  */
+#define _POSIX_PTHREAD_SEMANTICS 1
+/* Enable strtoimax on Solaris 10.  */
+#define __EXTENSIONS__ 1
+
 /*
 ** Nested includes
 */
 
+/* Avoid clashes with NetBSD by renaming NetBSD's declarations.  */
+#define localtime_rz sys_localtime_rz
+#define mktime_z sys_mktime_z
+#define posix2time_z sys_posix2time_z
+#define time2posix_z sys_time2posix_z
+#define timezone_t sys_timezone_t
+#define tzalloc sys_tzalloc
+#define tzfree sys_tzfree
+#include <time.h>
+#undef localtime_rz
+#undef mktime_z
+#undef posix2time_z
+#undef time2posix_z
+#undef timezone_t
+#undef tzalloc
+#undef tzfree
+
 #include "sys/types.h"	/* for time_t */
 #include "stdio.h"
-#include "errno.h"
 #include "string.h"
 #include "limits.h"	/* for CHAR_BIT et al. */
-#include "time.h"
 #include "stdlib.h"
 
+#include "errno.h"
+
+#ifndef ENAMETOOLONG
+# define ENAMETOOLONG EINVAL
+#endif
+#ifndef EOVERFLOW
+# define EOVERFLOW EINVAL
+#endif
+
 #if HAVE_GETTEXT
 #include "libintl.h"
 #endif /* HAVE_GETTEXT */
@@ -104,6 +129,14 @@
 #include "unistd.h"	/* for F_OK, R_OK, and other POSIX goodness */
 #endif /* HAVE_UNISTD_H */
 
+#ifndef HAVE_STRFTIME_L
+# if _POSIX_VERSION < 200809
+#  define HAVE_STRFTIME_L 0
+# else
+#  define HAVE_STRFTIME_L 1
+# endif
+#endif
+
 #ifndef F_OK
 #define F_OK	0
 #endif /* !defined F_OK */
@@ -138,65 +171,98 @@
 # include <inttypes.h>
 #endif
 
-#ifndef INT_FAST64_MAX
 /* Pre-C99 GCC compilers define __LONG_LONG_MAX__ instead of LLONG_MAX.  */
-#if defined LLONG_MAX || defined __LONG_LONG_MAX__
-typedef long long	int_fast64_t;
+#ifdef __LONG_LONG_MAX__
+# ifndef LLONG_MAX
+#  define LLONG_MAX __LONG_LONG_MAX__
+# endif
+# ifndef LLONG_MIN
+#  define LLONG_MIN (-1 - LLONG_MAX)
+# endif
+#endif
+
+#ifndef INT_FAST64_MAX
 # ifdef LLONG_MAX
+typedef long long	int_fast64_t;
 #  define INT_FAST64_MIN LLONG_MIN
 #  define INT_FAST64_MAX LLONG_MAX
 # else
-#  define INT_FAST64_MIN __LONG_LONG_MIN__
-#  define INT_FAST64_MAX __LONG_LONG_MAX__
-# endif
-# define SCNdFAST64 "lld"
-#else /* ! (defined LLONG_MAX || defined __LONG_LONG_MAX__) */
-#if (LONG_MAX >> 31) < 0xffffffff
+#  if LONG_MAX >> 31 < 0xffffffff
 Please use a compiler that supports a 64-bit integer type (or wider);
 you may need to compile with "-DHAVE_STDINT_H".
-#endif /* (LONG_MAX >> 31) < 0xffffffff */
+#  endif
 typedef long		int_fast64_t;
-# define INT_FAST64_MIN LONG_MIN
-# define INT_FAST64_MAX LONG_MAX
-# define SCNdFAST64 "ld"
-#endif /* ! (defined LLONG_MAX || defined __LONG_LONG_MAX__) */
-#endif /* !defined INT_FAST64_MAX */
+#  define INT_FAST64_MIN LONG_MIN
+#  define INT_FAST64_MAX LONG_MAX
+# endif
+#endif
+
+#ifndef SCNdFAST64
+# if INT_FAST64_MAX == LLONG_MAX
+#  define SCNdFAST64 "lld"
+# else
+#  define SCNdFAST64 "ld"
+# endif
+#endif
 
 #ifndef INT_FAST32_MAX
 # if INT_MAX >> 31 == 0
 typedef long int_fast32_t;
+#  define INT_FAST32_MAX LONG_MAX
+#  define INT_FAST32_MIN LONG_MIN
 # else
 typedef int int_fast32_t;
+#  define INT_FAST32_MAX INT_MAX
+#  define INT_FAST32_MIN INT_MIN
 # endif
 #endif
 
 #ifndef INTMAX_MAX
-# if defined LLONG_MAX || defined __LONG_LONG_MAX__
+# ifdef LLONG_MAX
 typedef long long intmax_t;
 #  define strtoimax strtoll
-#  define PRIdMAX "lld"
-#  ifdef LLONG_MAX
-#   define INTMAX_MAX LLONG_MAX
-#   define INTMAX_MIN LLONG_MIN
-#  else
-#   define INTMAX_MAX __LONG_LONG_MAX__
-#   define INTMAX_MIN __LONG_LONG_MIN__
-#  endif
+#  define INTMAX_MAX LLONG_MAX
+#  define INTMAX_MIN LLONG_MIN
 # else
 typedef long intmax_t;
 #  define strtoimax strtol
-#  define PRIdMAX "ld"
 #  define INTMAX_MAX LONG_MAX
 #  define INTMAX_MIN LONG_MIN
 # endif
 #endif
 
+#ifndef PRIdMAX
+# if INTMAX_MAX == LLONG_MAX
+#  define PRIdMAX "lld"
+# else
+#  define PRIdMAX "ld"
+# endif
+#endif
+
+#ifndef UINT_FAST64_MAX
+# if defined ULLONG_MAX || defined __LONG_LONG_MAX__
+typedef unsigned long long uint_fast64_t;
+# else
+#  if ULONG_MAX >> 31 >> 1 < 0xffffffff
+Please use a compiler that supports a 64-bit integer type (or wider);
+you may need to compile with "-DHAVE_STDINT_H".
+#  endif
+typedef unsigned long	uint_fast64_t;
+# endif
+#endif
+
 #ifndef UINTMAX_MAX
 # if defined ULLONG_MAX || defined __LONG_LONG_MAX__
 typedef unsigned long long uintmax_t;
-#  define PRIuMAX "llu"
 # else
 typedef unsigned long uintmax_t;
+# endif
+#endif
+
+#ifndef PRIuMAX
+# if defined ULLONG_MAX || defined __LONG_LONG_MAX__
+#  define PRIuMAX "llu"
+# else
 #  define PRIuMAX "lu"
 # endif
 #endif
@@ -239,16 +305,6 @@
 */
 
 /*
-** Some time.h implementations don't declare asctime_r.
-** Others might define it as a macro.
-** Fix the former without affecting the latter.
-*/
-
-#ifndef asctime_r
-extern char *	asctime_r(struct tm const *, char *);
-#endif
-
-/*
 ** Compile with -Dtime_tz=T to build the tz package with a private
 ** time_t type equivalent to T rather than the system-supplied time_t.
 ** This debugging feature can test unusual design decisions
@@ -256,7 +312,11 @@
 ** typical platforms.
 */
 #ifdef time_tz
+# ifdef LOCALTIME_IMPLEMENTATION
 static time_t sys_time(time_t *x) { return time(x); }
+# endif
+
+typedef time_tz tz_time_t;
 
 # undef  ctime
 # define ctime tz_ctime
@@ -272,14 +332,40 @@
 # define localtime tz_localtime
 # undef  localtime_r
 # define localtime_r tz_localtime_r
+# undef  localtime_rz
+# define localtime_rz tz_localtime_rz
 # undef  mktime
 # define mktime tz_mktime
+# undef  mktime_z
+# define mktime_z tz_mktime_z
+# undef  offtime
+# define offtime tz_offtime
+# undef  posix2time
+# define posix2time tz_posix2time
+# undef  posix2time_z
+# define posix2time_z tz_posix2time_z
 # undef  time
 # define time tz_time
+# undef  time2posix
+# define time2posix tz_time2posix
+# undef  time2posix_z
+# define time2posix_z tz_time2posix_z
 # undef  time_t
 # define time_t tz_time_t
-
-typedef time_tz time_t;
+# undef  timegm
+# define timegm tz_timegm
+# undef  timelocal
+# define timelocal tz_timelocal
+# undef  timeoff
+# define timeoff tz_timeoff
+# undef  tzalloc
+# define tzalloc tz_tzalloc
+# undef  tzfree
+# define tzfree tz_tzfree
+# undef  tzset
+# define tzset tz_tzset
+# undef  tzsetwall
+# define tzsetwall tz_tzsetwall
 
 char *ctime(time_t const *);
 char *ctime_r(time_t const *, char *);
@@ -289,36 +375,111 @@
 struct tm *localtime(time_t const *);
 struct tm *localtime_r(time_t const *restrict, struct tm *restrict);
 time_t mktime(struct tm *);
-
-static time_t
-time(time_t *p)
-{
-	time_t r = sys_time(0);
-	if (p)
-		*p = r;
-	return r;
-}
+time_t time(time_t *);
+void tzset(void);
 #endif
 
 /*
-** Private function declarations.
+** Some time.h implementations don't declare asctime_r.
+** Others might define it as a macro.
+** Fix the former without affecting the latter.
+** Similarly for timezone, daylight, and altzone.
 */
 
-char *		icatalloc(char * old, const char * new);
-char *		icpyalloc(const char * string);
-const char *	scheck(const char * string, const char * format);
+#ifndef asctime_r
+extern char *	asctime_r(struct tm const *restrict, char *restrict);
+#endif
+
+#ifdef USG_COMPAT
+# ifndef timezone
+extern long timezone;
+# endif
+# ifndef daylight
+extern int daylight;
+# endif
+#endif
+#if defined ALTZONE && !defined altzone
+extern long altzone;
+#endif
+
+/*
+** The STD_INSPIRED functions are similar, but most also need
+** declarations if time_tz is defined.
+*/
+
+#ifdef STD_INSPIRED
+# if !defined tzsetwall || defined time_tz
+void tzsetwall(void);
+# endif
+# if !defined offtime || defined time_tz
+struct tm *offtime(time_t const *, long);
+# endif
+# if !defined timegm || defined time_tz
+time_t timegm(struct tm *);
+# endif
+# if !defined timelocal || defined time_tz
+time_t timelocal(struct tm *);
+# endif
+# if !defined timeoff || defined time_tz
+time_t timeoff(struct tm *, long);
+# endif
+# if !defined time2posix || defined time_tz
+time_t time2posix(time_t);
+# endif
+# if !defined posix2time || defined time_tz
+time_t posix2time(time_t);
+# endif
+#endif
+
+/* Infer TM_ZONE on systems where this information is known, but suppress
+   guessing if NO_TM_ZONE is defined.  Similarly for TM_GMTOFF.  */
+#if (defined __GLIBC__ \
+     || defined __FreeBSD__ || defined __NetBSD__ || defined __OpenBSD__ \
+     || (defined __APPLE__ && defined __MACH__))
+# if !defined TM_GMTOFF && !defined NO_TM_GMTOFF
+#  define TM_GMTOFF tm_gmtoff
+# endif
+# if !defined TM_ZONE && !defined NO_TM_ZONE
+#  define TM_ZONE tm_zone
+# endif
+#endif
+
+/*
+** Define functions that are ABI compatible with NetBSD but have
+** better prototypes.  NetBSD 6.1.4 defines a pointer type timezone_t
+** and labors under the misconception that 'const timezone_t' is a
+** pointer to a constant.  This use of 'const' is ineffective, so it
+** is not done here.  What we call 'struct state' NetBSD calls
+** 'struct __state', but this is a private name so it doesn't matter.
+*/
+#if NETBSD_INSPIRED
+typedef struct state *timezone_t;
+struct tm *localtime_rz(timezone_t restrict, time_t const *restrict,
+			struct tm *restrict);
+time_t mktime_z(timezone_t restrict, struct tm *restrict);
+timezone_t tzalloc(char const *);
+void tzfree(timezone_t);
+# ifdef STD_INSPIRED
+#  if !defined posix2time_z || defined time_tz
+time_t posix2time_z(timezone_t, time_t) ATTRIBUTE_PURE;
+#  endif
+#  if !defined time2posix_z || defined time_tz
+time_t time2posix_z(timezone_t, time_t) ATTRIBUTE_PURE;
+#  endif
+# endif
+#endif
 
 /*
 ** Finally, some convenience items.
 */
 
-#ifndef TRUE
-#define TRUE	1
-#endif /* !defined TRUE */
-
-#ifndef FALSE
-#define FALSE	0
-#endif /* !defined FALSE */
+#if __STDC_VERSION__ < 199901
+# define true 1
+# define false 0
+# define bool int
+#else
+# include <stdbool.h>
+#endif
 
 #ifndef TYPE_BIT
 #define TYPE_BIT(type)	(sizeof (type) * CHAR_BIT)
@@ -330,14 +491,14 @@
 
 #define TWOS_COMPLEMENT(t) ((t) ~ (t) 0 < 0)
 
-  /* Max and min values of the integer type T, of which only the bottom
-   *    B bits are used, and where the highest-order used bit is considered
-   *       to be a sign bit if T is signed.  */
-#define MAXVAL(t, b)            \
-      ((t) (((t) 1 << ((b) - 1 - TYPE_SIGNED(t)))     \
-          - 1 + ((t) 1 << ((b) - 1 - TYPE_SIGNED(t)))))
-#define MINVAL(t, b)            \
-      ((t) (TYPE_SIGNED(t) ? - TWOS_COMPLEMENT(t) - MAXVAL(t, b) : 0))
+/* Max and min values of the integer type T, of which only the bottom
+   B bits are used, and where the highest-order used bit is considered
+   to be a sign bit if T is signed.  */
+#define MAXVAL(t, b)						\
+  ((t) (((t) 1 << ((b) - 1 - TYPE_SIGNED(t)))			\
+	- 1 + ((t) 1 << ((b) - 1 - TYPE_SIGNED(t)))))
+#define MINVAL(t, b)						\
+  ((t) (TYPE_SIGNED(t) ? - TWOS_COMPLEMENT(t) - MAXVAL(t, b) : 0))
 
 /* The minimum and maximum finite time values.  This assumes no padding.  */
 static time_t const time_t_min = MINVAL(time_t, TYPE_BIT(time_t));
@@ -365,6 +526,10 @@
 # define INITIALIZE(x)
 #endif
 
+#ifndef UNINIT_TRAP
+# define UNINIT_TRAP 0
+#endif
+
 /*
 ** For the benefit of GNU folk...
 ** '_(MSGID)' uses the current locale's message library string for MSGID.
@@ -379,7 +544,7 @@
 #endif /* !HAVE_GETTEXT */
 #endif /* !defined _ */
 
-#if !defined TZ_DOMAIN && defined TZ_DOMAINDIR
+#if !defined TZ_DOMAIN && defined HAVE_GETTEXT
 # define TZ_DOMAIN "tz"
 #endif
 
@@ -410,8 +575,4 @@
 #define SECSPERREPEAT_BITS	34	/* ceil(log2(SECSPERREPEAT)) */
 #endif /* !defined SECSPERREPEAT_BITS */
 
-/*
-** UNIX was a registered trademark of The Open Group in 2003.
-*/
-
 #endif /* !defined PRIVATE_H */
diff --git a/libc/tzcode/strftime.c b/libc/tzcode/strftime.c
index 4328b4c..10dfb4b 100644
--- a/libc/tzcode/strftime.c
+++ b/libc/tzcode/strftime.c
@@ -55,15 +55,7 @@
     const char *    date_fmt;
 };
 
-#ifdef LOCALE_HOME
-#include "sys/stat.h"
-static struct lc_time_T                localebuf;
-static struct lc_time_T *      _loc(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 = {
     {
@@ -115,7 +107,7 @@
 static char *   _conv(int, const char *, char *, const char *);
 static char *   _fmt(const char *, const struct tm *, char *, const char *,
             int *);
-static char *   _yconv(int, int, int, int, char *, const char *, int);
+static char *   _yconv(int, int, bool, bool, char *, const char *, int);
 static char *   getformat(int, char *, char *, char *, char *);
 
 extern char *   tzname[];
@@ -132,32 +124,28 @@
 #define FORCE_LOWER_CASE 0x100
 
 size_t
-strftime(char * const s, const size_t maxsize, const char *const format,
-        const struct tm *const t)
+strftime(char *s, size_t maxsize, const char *format, const struct tm *t)
 {
     char *  p;
     int warn;
 
     tzset();
-#ifdef LOCALE_HOME
-    localebuf.mon[0] = 0;
-#endif /* defined LOCALE_HOME */
     warn = IN_NONE;
     p = _fmt(((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");
+        fprintf(stderr, "\n");
         if (format == NULL)
-            (void) fprintf(stderr, "NULL strftime format ");
-        else    (void) fprintf(stderr, "strftime format \"%s\" ",
+            fprintf(stderr, "NULL strftime format ");
+        else    fprintf(stderr, "strftime format \"%s\" ",
                 format);
-        (void) fprintf(stderr, "yields only two digits of years in ");
+        fprintf(stderr, "yields only two digits of years in ");
         if (warn == IN_SOME)
-            (void) fprintf(stderr, "some locales");
+            fprintf(stderr, "some locales");
         else if (warn == IN_THIS)
-            (void) fprintf(stderr, "the current locale");
-        else    (void) fprintf(stderr, "all locales");
-        (void) fprintf(stderr, "\n");
+            fprintf(stderr, "the current locale");
+        else    fprintf(stderr, "all locales");
+        fprintf(stderr, "\n");
     }
 #endif /* !defined NO_RUN_TIME_WARNINGS_ABOUT_YEAR_2000_PROBLEMS_THANK_YOU */
     if (p == s + maxsize)
@@ -171,20 +159,17 @@
     switch (modifier) {
     case '_':
         return underscore;
-
     case '-':
         return dash;
-
     case '0':
         return zero;
     }
-
     return normal;
 }
 
 static char *
-_fmt(const char *format, const struct tm *const t, char * pt,
-        const char *const ptlim, int *warnp)
+_fmt(const char *format, const struct tm *t, char *pt,
+        const char *ptlim, int *warnp)
 {
     for ( ; *format; ++format) {
         if (*format == '%') {
@@ -227,8 +212,8 @@
                 ** something completely different.
                 ** (ado, 1993-05-24)
                 */
-                pt = _yconv(t->tm_year, TM_YEAR_BASE, 1, 0,
-                    pt, ptlim, modifier);
+                pt = _yconv(t->tm_year, TM_YEAR_BASE,
+                    true, false, pt, ptlim, modifier);
                 continue;
             case 'c':
                 {
@@ -245,10 +230,7 @@
                                 pt = _fmt("%m/%d/%y", t, pt, ptlim, warnp);
                 continue;
             case 'd':
-                                pt = _conv(t->tm_mday,
-                                           getformat(modifier, "%02d",
-                                                     "%2d", "%d", "%02d"),
-                                           pt, ptlim);
+                                pt = _conv(t->tm_mday, getformat(modifier, "%02d", "%2d", "%d", "%02d"), pt, ptlim);
                 continue;
             case 'E':
             case 'O':
@@ -270,31 +252,21 @@
                 modifier = *format;
                 goto label;
             case 'e':
-                pt = _conv(t->tm_mday,
-                                           getformat(modifier, "%2d",
-                                                     "%2d", "%d", "%02d"),
-                                           pt, ptlim);
+                pt = _conv(t->tm_mday, getformat(modifier, "%2d", "%2d", "%d", "%02d"), pt, ptlim);
                 continue;
             case 'F':
                 pt = _fmt("%Y-%m-%d", t, pt, ptlim, warnp);
                 continue;
             case 'H':
-                pt = _conv(t->tm_hour,
-                                           getformat(modifier, "%02d",
-                                                     "%2d", "%d", "%02d"),
-                                           pt, ptlim);
+                pt = _conv(t->tm_hour, getformat(modifier, "%02d", "%2d", "%d", "%02d"), pt, ptlim);
                 continue;
             case 'I':
                 pt = _conv((t->tm_hour % 12) ?
                     (t->tm_hour % 12) : 12,
-                    getformat(modifier, "%02d",
-                                                  "%2d", "%d", "%02d"),
-                                        pt, ptlim);
+                    getformat(modifier, "%02d", "%2d", "%d", "%02d"), pt, ptlim);
                 continue;
             case 'j':
-                pt = _conv(t->tm_yday + 1,
-                           getformat(modifier, "%03d", "%3d", "%d", "%03d"),
-                           pt, ptlim);
+                pt = _conv(t->tm_yday + 1, getformat(modifier, "%03d", "%3d", "%d", "%03d"), pt, ptlim);
                 continue;
             case 'k':
                 /*
@@ -307,10 +279,7 @@
                 ** "%l" have been swapped.
                 ** (ado, 1993-05-24)
                 */
-                pt = _conv(t->tm_hour,
-                                           getformat(modifier, "%2d",
-                                                     "%2d", "%d", "%02d"),
-                                           pt, ptlim);
+                pt = _conv(t->tm_hour, getformat(modifier, "%2d", "%2d", "%d", "%02d"), pt, ptlim);
                 continue;
 #ifdef KITCHEN_SINK
             case 'K':
@@ -332,36 +301,23 @@
                 */
                 pt = _conv((t->tm_hour % 12) ?
                     (t->tm_hour % 12) : 12,
-                    getformat(modifier, "%2d",
-                                                  "%2d", "%d", "%02d"),
-                                        pt, ptlim);
+                    getformat(modifier, "%2d", "%2d", "%d", "%02d"), pt, ptlim);
                 continue;
             case 'M':
-                pt = _conv(t->tm_min,
-                                           getformat(modifier, "%02d",
-                                                     "%2d", "%d", "%02d"),
-                                           pt, ptlim);
+                pt = _conv(t->tm_min, getformat(modifier, "%02d", "%2d", "%d", "%02d"), pt, ptlim);
                 continue;
             case 'm':
-                pt = _conv(t->tm_mon + 1,
-                                           getformat(modifier, "%02d",
-                                                     "%2d", "%d", "%02d"),
-                                           pt, ptlim);
+                pt = _conv(t->tm_mon + 1, getformat(modifier, "%02d", "%2d", "%d", "%02d"), pt, ptlim);
                 continue;
             case 'n':
                 pt = _add("\n", pt, ptlim, modifier);
                 continue;
+            case 'P':
             case 'p':
                 pt = _add((t->tm_hour >= (HOURSPERDAY / 2)) ?
                     Locale->pm :
                     Locale->am,
-                    pt, ptlim, modifier);
-                continue;
-            case 'P':
-                pt = _add((t->tm_hour >= (HOURSPERDAY / 2)) ?
-                    Locale->pm :
-                    Locale->am,
-                    pt, ptlim, FORCE_LOWER_CASE);
+                    pt, ptlim, (*format == 'P') ? FORCE_LOWER_CASE : modifier);
                 continue;
             case 'R':
                 pt = _fmt("%H:%M", t, pt, ptlim, warnp);
@@ -370,10 +326,7 @@
                 pt = _fmt("%I:%M:%S %p", t, pt, ptlim, warnp);
                 continue;
             case 'S':
-                pt = _conv(t->tm_sec,
-                                           getformat(modifier, "%02d",
-                                                     "%2d", "%d", "%02d"),
-                                           pt, ptlim);
+                pt = _conv(t->tm_sec, getformat(modifier, "%02d", "%2d", "%d", "%02d"), pt, ptlim);
                 continue;
             case 's':
                 {
@@ -385,10 +338,10 @@
                     tm = *t;
                     mkt = mktime64(&tm);
                     if (TYPE_SIGNED(time64_t))
-                        (void) snprintf(buf, sizeof(buf), "%lld",
-                            (long long) mkt);
-                    else    (void) snprintf(buf, sizeof(buf), "%llu",
-                            (unsigned long long) mkt);
+                        snprintf(buf, sizeof(buf), "%"PRIdMAX,
+                                 (intmax_t) mkt);
+                    else    snprintf(buf, sizeof(buf), "%"PRIuMAX,
+                                     (uintmax_t) mkt);
                     pt = _add(buf, pt, ptlim, modifier);
                 }
                 continue;
@@ -401,9 +354,7 @@
             case 'U':
                 pt = _conv((t->tm_yday + DAYSPERWEEK -
                     t->tm_wday) / DAYSPERWEEK,
-                    getformat(modifier, "%02d",
-                                                  "%2d", "%d", "%02d"),
-                                        pt, ptlim);
+                    getformat(modifier, "%02d", "%2d", "%d", "%02d"), pt, ptlim);
                 continue;
             case 'u':
                 /*
@@ -413,7 +364,8 @@
                 ** (ado, 1993-05-24)
                 */
                 pt = _conv((t->tm_wday == 0) ?
-                    DAYSPERWEEK : t->tm_wday, "%d", pt, ptlim);
+                    DAYSPERWEEK : t->tm_wday,
+                    "%d", pt, ptlim);
                 continue;
             case 'V':   /* ISO 8601 week number */
             case 'G':   /* ISO 8601 year (four digits) */
@@ -493,14 +445,15 @@
                             w = 53;
 #endif /* defined XPG4_1994_04_09 */
                     if (*format == 'V')
-                        pt = _conv(w,
-                                getformat(modifier, "%02d", "%2d", "%d", "%02d"),
+                        pt = _conv(w, getformat(modifier, "%02d", "%2d", "%d", "%02d"),
                                pt, ptlim);
                     else if (*format == 'g') {
                         *warnp = IN_ALL;
-                        pt = _yconv(year, base, 0, 1,
+                        pt = _yconv(year, base,
+                            false, true,
                             pt, ptlim, modifier);
-                    } else  pt = _yconv(year, base, 1, 1,
+                    } else  pt = _yconv(year, base,
+                            true, true,
                             pt, ptlim, modifier);
                 }
                 continue;
@@ -517,9 +470,7 @@
                     (t->tm_wday ?
                     (t->tm_wday - 1) :
                     (DAYSPERWEEK - 1))) / DAYSPERWEEK,
-                    getformat(modifier, "%02d",
-                                                  "%2d", "%d", "%02d"),
-                                        pt, ptlim);
+                    getformat(modifier, "%02d", "%2d", "%d", "%02d"), pt, ptlim);
                 continue;
             case 'w':
                 pt = _conv(t->tm_wday, "%d", pt, ptlim);
@@ -540,23 +491,23 @@
                 continue;
             case 'y':
                 *warnp = IN_ALL;
-                pt = _yconv(t->tm_year, TM_YEAR_BASE, 0, 1,
+                pt = _yconv(t->tm_year, TM_YEAR_BASE,
+                    false, true,
                     pt, ptlim, modifier);
                 continue;
             case 'Y':
-                pt = _yconv(t->tm_year, TM_YEAR_BASE, 1, 1,
+                pt = _yconv(t->tm_year, TM_YEAR_BASE,
+                    true, true,
                     pt, ptlim, modifier);
                 continue;
             case 'Z':
 #ifdef TM_ZONE
-                if (t->TM_ZONE != NULL)
-                    pt = _add(t->TM_ZONE, pt, ptlim,
-                                                  modifier);
-                else
-#endif /* defined TM_ZONE */
+                pt = _add(t->TM_ZONE, pt, ptlim, modifier);
+#else
                 if (t->tm_isdst >= 0)
                     pt = _add(tzname[t->tm_isdst != 0],
-                        pt, ptlim, modifier);
+                        pt, ptlim);
+#endif
                 /*
                 ** C99 says that %Z must be replaced by the
                 ** empty string if the time zone is not
@@ -613,10 +564,7 @@
                 diff /= SECSPERMIN;
                 diff = (diff / MINSPERHOUR) * 100 +
                     (diff % MINSPERHOUR);
-                pt = _conv(diff,
-                                           getformat(modifier, "%04d",
-                                                     "%4d", "%d", "%04d"),
-                                           pt, ptlim);
+                pt = _conv(diff, getformat(modifier, "%04d", "%4d", "%d", "%04d"), pt, ptlim);
                 }
                 continue;
             case '+':
@@ -641,13 +589,12 @@
 }
 
 static char *
-_conv(const int n, const char *const format, char *const pt,
-        const char *const ptlim)
+_conv(int n, const char *format, char *pt, const char *ptlim)
 {
-    char    buf[INT_STRLEN_MAXIMUM(int) + 1];
+	char	buf[INT_STRLEN_MAXIMUM(int) + 1];
 
-    (void) snprintf(buf, sizeof(buf), format, n);
-    return _add(buf, pt, ptlim, 0);
+	snprintf(buf, sizeof(buf), format, n);
+	return _add(buf, pt, ptlim, 0);
 }
 
 static char *
@@ -699,8 +646,8 @@
 */
 
 static char *
-_yconv(const int a, const int b, const int convert_top, const int convert_yy,
-        char *pt, const char *const ptlim, int modifier)
+_yconv(int a, int b, bool convert_top, bool convert_yy,
+       char *pt, const char *ptlim, int modifier)
 {
     register int    lead;
     register int    trail;
diff --git a/libc/tzcode/tzfile.h b/libc/tzcode/tzfile.h
index 529650d..ebecd68 100644
--- a/libc/tzcode/tzfile.h
+++ b/libc/tzcode/tzfile.h
@@ -40,7 +40,7 @@
 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_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 */
@@ -62,13 +62,13 @@
 **	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,
+**	tzh_ttisstdcnt (char)s		indexed by type; if 1, transition
+**					time is standard time, if 0,
 **					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,
+**	tzh_ttisgmtcnt (char)s		indexed by type; if 1, transition
+**					time is UT, if 0,
 **					transition time is local time
 **					if absent, transition times are
 **					assumed to be local time
@@ -97,7 +97,7 @@
 */
 
 #ifndef TZ_MAX_TIMES
-#define TZ_MAX_TIMES	1200
+#define TZ_MAX_TIMES	2000
 #endif /* !defined TZ_MAX_TIMES */
 
 #ifndef TZ_MAX_TYPES