Upgrade to tzcode2013d.

Well, kinda... localtime.c still contains a bunch of Android-specific
hacks, as does strftime.c. But the other files are now exactly the same
as upstream.

This catches up with several years of bug fixes, and fixes most of the
compiler warnings that were in this code. (Just two remain.)

Bug: 1744909
Change-Id: I2ddfecb6fd408c847397c17afb0fff859e27feef
diff --git a/libc/tzcode/localtime.c b/libc/tzcode/localtime.c
index 0c4d268..d1b49e5 100644
--- a/libc/tzcode/localtime.c
+++ b/libc/tzcode/localtime.c
@@ -3,12 +3,6 @@
 ** 1996-06-05 by Arthur David Olson.
 */
 
-#ifndef lint
-#ifndef NOID
-static char elsieid[] = "@(#)localtime.c    8.3";
-#endif /* !defined NOID */
-#endif /* !defined lint */
-
 /*
 ** Leap second handling from Bradley White.
 ** POSIX-style TZ environment variable handling from Guy Harris.
@@ -21,9 +15,6 @@
 #include "fcntl.h"
 #include "float.h"  /* for FLT_MAX and DBL_MAX */
 
-#include "thread_private.h"
-#include <sys/system_properties.h>
-
 #ifndef TZ_ABBR_MAX_LEN
 #define TZ_ABBR_MAX_LEN 16
 #endif /* !defined TZ_ABBR_MAX_LEN */
@@ -54,53 +45,12 @@
 #  define  XLOG(x)   do{}while (0)
 #endif
 
-/* Add the following function implementations:
- *  timelocal()
- *  timegm()
- *  time2posix()
- *  posix2time()
- */
-#define STD_INSPIRED 1
-
-/* THREAD-SAFETY SUPPORT GOES HERE */
-static pthread_mutex_t  _tzMutex = PTHREAD_MUTEX_INITIALIZER;
-
-static __inline__ void _tzLock(void)
-{
-    if (__isthreaded)
-        pthread_mutex_lock(&_tzMutex);
-}
-
-static __inline__ void _tzUnlock(void)
-{
-    if (__isthreaded)
-        pthread_mutex_unlock(&_tzMutex);
-}
-
-/* Complex computations to determine the min/max of time_t depending
- * on TYPE_BIT / TYPE_SIGNED / TYPE_INTEGRAL.
- * These macros cannot be used in pre-processor directives, so we
- * let the C compiler do the work, which makes things a bit funky.
- */
-static const time_t TIME_T_MAX =
-    TYPE_INTEGRAL(time_t) ?
-        ( TYPE_SIGNED(time_t) ?
-            ~((time_t)1 << (TYPE_BIT(time_t)-1))
-        :
-            ~(time_t)0
-        )
-    : /* if time_t is a floating point number */
-        ( sizeof(time_t) > sizeof(float) ? (time_t)DBL_MAX : (time_t)FLT_MAX );
-
-static const time_t TIME_T_MIN =
-    TYPE_INTEGRAL(time_t) ?
-        ( TYPE_SIGNED(time_t) ?
-            ((time_t)1 << (TYPE_BIT(time_t)-1))
-        :
-            0
-        )
-    :
-        ( sizeof(time_t) > sizeof(float) ? (time_t)DBL_MIN : (time_t)FLT_MIN );
+/* 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
 /*
@@ -141,16 +91,16 @@
 #endif /* !defined TZDEFDST */
 
 struct ttinfo {             /* time type information */
-    long    tt_gmtoff;  /* UTC offset in seconds */
-    int     tt_isdst;   /* used to set tm_isdst */
-    int     tt_abbrind; /* abbreviation list index */
-    int     tt_ttisstd; /* TRUE if transition is std time */
-    int     tt_ttisgmt; /* TRUE if transition is UTC */
+    int_fast32_t tt_gmtoff;  /* UTC offset in seconds */
+    int          tt_isdst;   /* used to set tm_isdst */
+    int          tt_abbrind; /* abbreviation list index */
+    int          tt_ttisstd; /* TRUE if transition is std time */
+    int          tt_ttisgmt; /* TRUE if transition is UTC */
 };
 
 struct lsinfo {             /* leap second information */
-    time_t      ls_trans;   /* transition time */
-    long        ls_corr;    /* correction to apply */
+    time_t       ls_trans;   /* transition time */
+    int_fast64_t ls_corr;    /* correction to apply */
 };
 
 #define BIGGEST(a, b)   (((a) > (b)) ? (a) : (b))
@@ -162,10 +112,6 @@
 #define MY_TZNAME_MAX   255
 #endif /* !defined TZNAME_MAX */
 
-/* XXX: This code should really use time64_t instead of time_t
- *      but we can't change it without re-generating the index
- *      file first with the correct data.
- */
 struct state {
     int     leapcnt;
     int     timecnt;
@@ -179,14 +125,15 @@
     char        chars[BIGGEST(BIGGEST(TZ_MAX_CHARS + 1, sizeof gmt),
                 (2 * (MY_TZNAME_MAX + 1)))];
     struct lsinfo   lsis[TZ_MAX_LEAPS];
+    int defaulttype; /* for early times or if no transitions */
 };
 
 struct rule {
-    int     r_type;     /* type of rule--see below */
-    int     r_day;      /* day number of rule */
-    int     r_week;     /* week number of rule */
-    int     r_mon;      /* month number of rule */
-    long        r_time;     /* transition time of rule */
+    int          r_type;     /* type of rule--see below */
+    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 */
@@ -200,51 +147,54 @@
 /* NOTE: all internal functions assume that _tzLock() was already called */
 
 static int __bionic_open_tzdata(const char*, int*);
-static long     detzcode P((const char * codep));
-static time_t   detzcode64 P((const char * codep));
-static int      differ_by_repeat P((time_t t1, time_t t0));
-static const char * getzname P((const char * strp));
-static const char * getqzname P((const char * strp, const int delim));
-static const char * getnum P((const char * strp, int * nump, int min,
-                int max));
-static const char * getsecs P((const char * strp, long * secsp));
-static const char * getoffset P((const char * strp, long * offsetp));
-static const char * getrule P((const char * strp, struct rule * rulep));
-static void     gmtload P((struct state * sp));
-static struct tm *  gmtsub P((const time_t * timep, long offset,
-                struct tm * tmp, const struct state * sp)); // android-changed: added sp.
-static struct tm *  localsub P((const time_t * timep, long offset,
-                struct tm * tmp, const struct state * sp)); // android-changed: added sp.
-static int      increment_overflow P((int * number, int delta));
-static int      leaps_thru_end_of P((int y));
-static int      long_increment_overflow P((long * number, int delta));
-static int      long_normalize_overflow P((long * tensptr,
-                int * unitsptr, int base));
-static int      normalize_overflow P((int * tensptr, int * unitsptr,
-                int base));
-static void     settzname P((void));
-static time_t       time1 P((struct tm * tmp,
-                struct tm * (*funcp) P((const time_t *,
-                long, struct tm *, const struct state *)), // android-changed: added state*.
-                long offset, const struct state * sp)); // android-changed: added sp.
-static time_t       time2 P((struct tm *tmp,
-                struct tm * (*funcp) P((const time_t *,
-                long, struct tm*, const struct state *)), // android-changed: added state*.
-                long offset, int * okayp, const struct state * sp)); // android-changed: added sp.
-static time_t       time2sub P((struct tm *tmp,
-                struct tm * (*funcp) P((const time_t *,
-                long, struct tm*, const struct state *)), // android-changed: added state*.
-                long offset, int * okayp, int do_norm_secs, const struct state * sp)); // android-change: added sp.
-static struct tm *  timesub P((const time_t * timep, long offset,
-                const struct state * sp, struct tm * tmp));
-static int      tmcomp P((const struct tm * atmp,
-                const struct tm * btmp));
-static time_t       transtime P((time_t janfirst, int year,
-                const struct rule * rulep, long offset));
-static int      tzload P((const char * name, struct state * sp,
-                int doextend));
-static int      tzparse P((const char * name, struct state * sp,
-                int lastditch));
+static int_fast32_t detzcode(const char * codep);
+static time_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, const int_fast32_t offset,
+                struct tm * tmp, const struct state * sp); // android-changed: added sp.
+static struct tm *  localsub(const time_t * timep, int_fast32_t offset,
+                struct tm * tmp, const 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      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 *, const struct state *), // android-changed: added state*.
+                int_fast32_t offset, const struct state * sp); // android-changed: added sp.
+static time_t       time2(struct tm * const tmp,
+                struct tm * (*const funcp)(const time_t *,
+                int_fast32_t, struct tm*, const struct state *), // android-changed: added state*.
+                int_fast32_t offset, int * okayp, const 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*, const struct state *), // android-changed: added state*.
+                int_fast32_t offset, int * okayp, int do_norm_secs, const 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 time_t transtime(time_t janfirst, 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);
 
 #ifdef ALL_STATE
 static struct state *   lclptr;
@@ -290,34 +240,32 @@
 time_t          altzone = 0;
 #endif /* defined ALTZONE */
 
-static long
-detzcode(codep)
-const char * const  codep;
+static int_fast32_t
+detzcode(const char *const codep)
 {
-    register long   result;
-    register int    i;
+	register int_fast32_t	result;
+	register int		i;
 
-    result = (codep[0] & 0x80) ? ~0L : 0;
-    for (i = 0; i < 4; ++i)
-        result = (result << 8) | (codep[i] & 0xff);
-    return result;
+	result = (codep[0] & 0x80) ? -1 : 0;
+	for (i = 0; i < 4; ++i)
+		result = (result << 8) | (codep[i] & 0xff);
+	return result;
 }
 
 static time_t
-detzcode64(codep)
-const char * const  codep;
+detzcode64(const char *const codep)
 {
-    register time_t result;
-    register int    i;
+	register time_t	result;
+	register int	i;
 
-    result = (codep[0] & 0x80) ?  (~(int_fast64_t) 0) : 0;
-    for (i = 0; i < 8; ++i)
-        result = result * 256 + (codep[i] & 0xff);
-    return result;
+	result = (codep[0] & 0x80) ?  (~(int_fast64_t) 0) : 0;
+	for (i = 0; i < 8; ++i)
+		result = result * 256 + (codep[i] & 0xff);
+	return result;
 }
 
 static void
-settzname P((void))
+settzname(void)
 {
     register struct state * const   sp = lclptr;
     register int            i;
@@ -337,25 +285,14 @@
         return;
     }
 #endif /* defined ALL_STATE */
-    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];
-#ifdef USG_COMPAT
-        if (ttisp->tt_isdst)
-            daylight = 1;
-        if (i == 0 || !ttisp->tt_isdst)
-            timezone = -(ttisp->tt_gmtoff);
-#endif /* defined USG_COMPAT */
-#ifdef ALTZONE
-        if (i == 0 || ttisp->tt_isdst)
-            altzone = -(ttisp->tt_gmtoff);
-#endif /* defined ALTZONE */
-    }
     /*
     ** 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[
@@ -363,6 +300,16 @@
 
         tzname[ttisp->tt_isdst] =
             &sp->chars[ttisp->tt_abbrind];
+#ifdef USG_COMPAT
+        if (ttisp->tt_isdst)
+            daylight = 1;
+        if (!ttisp->tt_isdst)
+            timezone = -(ttisp->tt_gmtoff);
+#endif /* defined USG_COMPAT */
+#ifdef ALTZONE
+        if (ttisp->tt_isdst)
+            altzone = -(ttisp->tt_gmtoff);
+#endif /* defined ALTZONE */
     }
     /*
     ** Finally, scrub the abbreviations.
@@ -385,113 +332,70 @@
 }
 
 static int
-differ_by_repeat(t1, t0)
-const time_t    t1;
-const time_t    t0;
+differ_by_repeat(const time_t t1, const time_t t0)
 {
-    if (TYPE_INTEGRAL(time_t) &&
-        TYPE_BIT(time_t) - TYPE_SIGNED(time_t) < SECSPERREPEAT_BITS)
-            return 0;
-#if SECSPERREPEAT_BITS <= 32  /* to avoid compiler warning (condition is always false) */
-        return (t1 - t0) == SECSPERREPEAT;
-#else
-        return 0;
-#endif
-}
-
-static int toint(unsigned char *s) {
-    return (s[0] << 24) | (s[1] << 16) | (s[2] << 8) | s[3];
+	if (TYPE_INTEGRAL(time_t) &&
+		TYPE_BIT(time_t) - TYPE_SIGNED(time_t) < SECSPERREPEAT_BITS)
+			return 0;
+	return t1 - t0 == SECSPERREPEAT;
 }
 
 static int
-tzload(const char* name, struct state* const sp, const int doextend)
+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;
-    union {
+    typedef union {
         struct tzhead   tzhead;
         char        buf[2 * sizeof(struct tzhead) +
                     2 * sizeof *sp +
                     4 * TZ_MAX_TIMES];
-    } u;
-    int                     toread = sizeof u.buf;
+    } u_t;
+#ifdef ALL_STATE
+    register u_t *			up;
 
-        if (name == NULL && (name = TZDEFAULT) == NULL) {
-                XLOG(("tzload: null 'name' parameter\n" ));
-                return -1;
-        }
-    {
-        register int    doaccess;
-        /*
-        ** 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];
-        char        *origname = (char*) name;
+    up = (u_t *) calloc(1, sizeof *up);
+    if (up == NULL)
+        return -1;
+#else /* !defined ALL_STATE */
+    u_t				u;
+    register u_t * const		up = &u;
+#endif /* !defined ALL_STATE */
 
-        if (name[0] == ':')
-            ++name;
-        doaccess = name[0] == '/';
-        if (!doaccess) {
-            if ((p = TZDIR) == NULL) {
-                XLOG(("tzload: null TZDIR macro ?\n" ));
-                return -1;
-            }
-            if ((strlen(p) + strlen(name) + 1) >= sizeof fullname) {
-                XLOG(( "tzload: path too long: %s/%s\n", p, name ));
-                return -1;
-            }
-            (void) strcpy(fullname, p);
-            (void) strcat(fullname, "/");
-            (void) strcat(fullname, name);
-            /*
-            ** Set doaccess if '.' (as in "../") shows up in name.
-            */
-            if (strchr(name, '.') != NULL)
-                doaccess = TRUE;
-            name = fullname;
-        }
-        if (doaccess && access(name, R_OK) != 0) {
-            XLOG(( "tzload: could not find '%s'\n", name ));
-            return -1;
-        }
-        if ((fid = open(name, OPEN_MODE)) == -1) {
-            fid = __bionic_open_tzdata(origname, &toread);
-            if (fid < 0) {
-                return -1;
-            }
-        }
+    sp->goback = sp->goahead = FALSE;
+    if (name == NULL && (name = TZDEFAULT) == NULL)
+        goto oops;
+    int toread;
+    fid = __bionic_open_tzdata(name, &toread);
+    if (fid < 0) {
+        return -1;
     }
-    nread = read(fid, u.buf, toread);
-        if (close(fid) < 0 || nread <= 0) {
-            XLOG(( "tzload: could not read content of '%s'\n", DATAFILE ));
-            return -1;
-        }
+    nread = read(fid, up->buf, toread);
+    if (close(fid) < 0 || nread <= 0)
+        goto oops;
     for (stored = 4; stored <= 8; stored *= 2) {
         int     ttisstdcnt;
         int     ttisgmtcnt;
 
-        ttisstdcnt = (int) detzcode(u.tzhead.tzh_ttisstdcnt);
-        ttisgmtcnt = (int) detzcode(u.tzhead.tzh_ttisgmtcnt);
-        sp->leapcnt = (int) detzcode(u.tzhead.tzh_leapcnt);
-        sp->timecnt = (int) detzcode(u.tzhead.tzh_timecnt);
-        sp->typecnt = (int) detzcode(u.tzhead.tzh_typecnt);
-        sp->charcnt = (int) detzcode(u.tzhead.tzh_charcnt);
-        p = u.tzhead.tzh_charcnt + sizeof u.tzhead.tzh_charcnt;
+        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))
-                return -1;
-        if (nread - (p - u.buf) <
+                goto oops;
+        if (nread - (p - up->buf) <
             sp->timecnt * stored +      /* ats */
             sp->timecnt +           /* types */
             sp->typecnt * 6 +       /* ttinfos */
@@ -499,7 +403,7 @@
             sp->leapcnt * (stored + 4) +    /* lsinfos */
             ttisstdcnt +            /* ttisstds */
             ttisgmtcnt)         /* ttisgmts */
-                return -1;
+                goto oops;
         for (i = 0; i < sp->timecnt; ++i) {
             sp->ats[i] = (stored == 4) ?
                 detzcode(p) : detzcode64(p);
@@ -508,7 +412,7 @@
         for (i = 0; i < sp->timecnt; ++i) {
             sp->types[i] = (unsigned char) *p++;
             if (sp->types[i] >= sp->typecnt)
-                return -1;
+                goto oops;
         }
         for (i = 0; i < sp->typecnt; ++i) {
             register struct ttinfo *    ttisp;
@@ -518,11 +422,11 @@
             p += 4;
             ttisp->tt_isdst = (unsigned char) *p++;
             if (ttisp->tt_isdst != 0 && ttisp->tt_isdst != 1)
-                return -1;
+                goto oops;
             ttisp->tt_abbrind = (unsigned char) *p++;
             if (ttisp->tt_abbrind < 0 ||
                 ttisp->tt_abbrind > sp->charcnt)
-                    return -1;
+                    goto oops;
         }
         for (i = 0; i < sp->charcnt; ++i)
             sp->chars[i] = *p++;
@@ -547,7 +451,7 @@
                 ttisp->tt_ttisstd = *p++;
                 if (ttisp->tt_ttisstd != TRUE &&
                     ttisp->tt_ttisstd != FALSE)
-                        return -1;
+                        goto oops;
             }
         }
         for (i = 0; i < sp->typecnt; ++i) {
@@ -560,7 +464,7 @@
                 ttisp->tt_ttisgmt = *p++;
                 if (ttisp->tt_ttisgmt != TRUE &&
                     ttisp->tt_ttisgmt != FALSE)
-                        return -1;
+                        goto oops;
             }
         }
         /*
@@ -568,36 +472,47 @@
         ** signed time_t system but using a data file with
         ** unsigned values (or vice versa).
         */
-        for (i = 0; i < sp->timecnt - 2; ++i)
-            if (sp->ats[i] > sp->ats[i + 1]) {
-                ++i;
-                if (TYPE_SIGNED(time_t)) {
-                    /*
-                    ** Ignore the end (easy).
-                    */
-                    sp->timecnt = i;
-                } else {
-                    /*
-                    ** Ignore the beginning (harder).
-                    */
-                    register int    j;
+        for (i = 0; i < sp->timecnt; ++i)
+            if ((i < sp->timecnt - 1 &&
+                sp->ats[i] > sp->ats[i + 1]) ||
+                (i == sp->timecnt - 1 && !TYPE_SIGNED(time_t) &&
+                sp->ats[i] >
+                ((stored == 4) ? INT32_MAX : INT64_MAX))) {
+                    if (TYPE_SIGNED(time_t)) {
+                        /*
+                        ** Ignore the end (easy).
+                        */
+                        sp->timecnt = i + 1;
+                    } else {
+                        /*
+                        ** Ignore the beginning (harder).
+                        */
+                        register int    j;
 
-                    for (j = 0; j + i < sp->timecnt; ++j) {
-                        sp->ats[j] = sp->ats[j + i];
-                        sp->types[j] = sp->types[j + i];
+                        /*
+                        ** Keep the record right before the
+                        ** epoch boundary,
+                        ** but tweak it so that it starts
+                        ** right with the epoch
+                        ** (thanks to Doug Bailey).
+                        */
+                        sp->ats[i] = 0;
+                        for (j = 0; j + i < sp->timecnt; ++j) {
+                            sp->ats[j] = sp->ats[j + i];
+                            sp->types[j] = sp->types[j + i];
+                        }
+                        sp->timecnt = j;
                     }
-                    sp->timecnt = j;
-                }
-                break;
+                    break;
             }
         /*
         ** If this is an old file, we're done.
         */
-        if (u.tzhead.tzh_version[0] == '\0')
+        if (up->tzhead.tzh_version[0] == '\0')
             break;
-        nread -= p - u.buf;
+        nread -= p - up->buf;
         for (i = 0; i < nread; ++i)
-            u.buf[i] = p[i];
+            up->buf[i] = p[i];
         /*
         ** If this is a narrow integer time_t system, we're done.
         */
@@ -605,13 +520,13 @@
             break;
     }
     if (doextend && nread > 2 &&
-        u.buf[0] == '\n' && u.buf[nread - 1] == '\n' &&
+        up->buf[0] == '\n' && up->buf[nread - 1] == '\n' &&
         sp->typecnt + 2 <= TZ_MAX_TYPES) {
             struct state    ts;
             register int    result;
 
-            u.buf[nread - 1] = '\0';
-            result = tzparse(&u.buf[1], &ts, FALSE);
+            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)
@@ -639,16 +554,87 @@
                     sp->ttis[sp->typecnt++] = ts.ttis[1];
             }
     }
-    i = 2 * YEARSPERREPEAT;
-    sp->goback = sp->goahead = sp->timecnt > i;
-    sp->goback &= sp->types[i] == sp->types[0] &&
-        differ_by_repeat(sp->ats[i], sp->ats[0]);
-    sp->goahead &=
-        sp->types[sp->timecnt - 1] == sp->types[sp->timecnt - 1 - i] &&
-        differ_by_repeat(sp->ats[sp->timecnt - 1],
-             sp->ats[sp->timecnt - 1 - i]);
-        XLOG(( "tzload: load ok !!\n" ));
-    return 0;
+    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] = {
@@ -667,8 +653,7 @@
 */
 
 static const char *
-getzname(strp)
-register const char *   strp;
+getzname(register const char * strp)
 {
     register char   c;
 
@@ -705,11 +690,7 @@
 */
 
 static const char *
-getnum(strp, nump, min, max)
-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;
@@ -738,9 +719,7 @@
 */
 
 static const char *
-getsecs(strp, secsp)
-register const char *   strp;
-long * const        secsp;
+getsecs(register const char *strp, int_fast32_t *const secsp)
 {
     int num;
 
@@ -753,7 +732,7 @@
     strp = getnum(strp, &num, 0, HOURSPERDAY * DAYSPERWEEK - 1);
     if (strp == NULL)
         return NULL;
-    *secsp = num * (long) SECSPERHOUR;
+    *secsp = num * (int_fast32_t) SECSPERHOUR;
     if (*strp == ':') {
         ++strp;
         strp = getnum(strp, &num, 0, MINSPERHOUR - 1);
@@ -780,9 +759,7 @@
 */
 
 static const char *
-getoffset(strp, offsetp)
-register const char *   strp;
-long * const        offsetp;
+getoffset(register const char *strp, int_fast32_t *const offsetp)
 {
     register int    neg = 0;
 
@@ -807,9 +784,7 @@
 */
 
 static const char *
-getrule(strp, rulep)
-const char *            strp;
-register struct rule * const    rulep;
+getrule(const char * strp, register struct rule * const rulep)
 {
     if (*strp == 'J') {
         /*
@@ -861,11 +836,8 @@
 */
 
 static time_t
-transtime(janfirst, year, rulep, offset)
-const time_t                janfirst;
-const int               year;
-register const struct rule * const  rulep;
-const long              offset;
+transtime(const time_t janfirst, const int year,
+          register const struct rule *const rulep, const int_fast32_t offset)
 {
     register int    leapyear;
     register time_t value;
@@ -956,21 +928,20 @@
 */
 
 static int
-tzparse(name, sp, lastditch)
-const char *            name;
-register struct state * const   sp;
-const int           lastditch;
+tzparse(const char * name, register struct state * const sp,
+        const int lastditch)
 {
     const char *            stdname;
     const char *            dstname;
     size_t              stdlen;
     size_t              dstlen;
-    long                stdoffset;
-    long                dstoffset;
-    register time_t *       atp;
+    int_fast32_t                stdoffset;
+    int_fast32_t                dstoffset;
+    register time_t *           atp;
     register unsigned char *    typep;
     register char *         cp;
     register int            load_result;
+    static struct ttinfo    zttinfo;
 
     INITIALIZE(dstname);
     stdname = name;
@@ -1002,7 +973,6 @@
     load_result = tzload(TZDEFRULES, sp, FALSE);
     if (load_result != 0)
         sp->leapcnt = 0;        /* so, we're off a little */
-    sp->timecnt = 0;
     if (*name != '\0') {
         if (*name == '<') {
             dstname = ++name;
@@ -1044,6 +1014,7 @@
             /*
             ** 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;
@@ -1053,6 +1024,7 @@
             atp = sp->ats;
             typep = sp->types;
             janfirst = 0;
+            sp->timecnt = 0;
             for (year = EPOCH_YEAR;
                 sp->timecnt + 2 <= TZ_MAX_TIMES;
                 ++year) {
@@ -1082,9 +1054,9 @@
                 janfirst = newfirst;
             }
         } else {
-            register long   theirstdoffset;
-            register long   theirdstoffset;
-            register long   theiroffset;
+            register int_fast32_t   theirstdoffset;
+            register int_fast32_t   theirdstoffset;
+            register int_fast32_t   theiroffset;
             register int    isdst;
             register int    i;
             register int    j;
@@ -1156,8 +1128,8 @@
             }
             /*
             ** Finally, fill in ttis.
-            ** ttisstd and ttisgmt need not be handled.
             */
+            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;
@@ -1170,6 +1142,7 @@
         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;
@@ -1191,15 +1164,21 @@
 }
 
 static void
-gmtload(sp)
-struct state * const    sp;
+gmtload(struct state * const sp)
 {
     if (tzload(gmt, sp, TRUE) != 0)
         (void) tzparse(gmt, sp, TRUE);
 }
 
-static void
-tzsetwall P((void))
+#ifndef STD_INSPIRED
+/*
+** A non-static declaration of tzsetwall in a system header file
+** may cause a warning about this upcoming static declaration...
+*/
+static
+#endif /* !defined STD_INSPIRED */
+void
+tzsetwall(void)
 {
     if (lcl_is_set < 0)
         return;
@@ -1207,29 +1186,32 @@
 
 #ifdef ALL_STATE
     if (lclptr == NULL) {
-        lclptr = (struct state *) malloc(sizeof *lclptr);
+        lclptr = calloc(1, sizeof *lclptr);
         if (lclptr == NULL) {
             settzname();    /* all we can do */
             return;
         }
     }
 #endif /* defined ALL_STATE */
-    if (tzload((char *) NULL, lclptr, TRUE) != 0)
+    if (tzload(NULL, lclptr, TRUE) != 0)
         gmtload(lclptr);
     settzname();
 }
 
+#include <sys/system_properties.h> // For __system_property_get.
+
 static void
-tzset_locked P((void))
+tzset_locked(void)
 {
     register const char *   name = NULL;
-    static char buf[PROP_VALUE_MAX];
 
     name = getenv("TZ");
 
     // try the "persist.sys.timezone" system property first
-    if (name == NULL && __system_property_get("persist.sys.timezone", buf) > 0)
+    static char buf[PROP_VALUE_MAX];
+    if (name == NULL && __system_property_get("persist.sys.timezone", buf) > 0) {
         name = buf;
+    }
 
     if (name == NULL) {
         tzsetwall();
@@ -1244,7 +1226,7 @@
 
 #ifdef ALL_STATE
     if (lclptr == NULL) {
-        lclptr = (struct state *) malloc(sizeof *lclptr);
+        lclptr = calloc(1, sizeof *lclptr);
         if (lclptr == NULL) {
             settzname();    /* all we can do */
             return;
@@ -1269,7 +1251,7 @@
 }
 
 void
-tzset P((void))
+tzset(void)
 {
     _tzLock();
     tzset_locked();
@@ -1287,11 +1269,8 @@
 
 /*ARGSUSED*/
 static struct tm *
-localsub(timep, offset, tmp, sp) // android-changed: added sp.
-const time_t * const    timep;
-const long      offset;
-struct tm * const   tmp;
-const struct state * sp; // android-added: added sp.
+localsub(const time_t * const timep, const int_fast32_t offset,
+         struct tm * const tmp, const struct state * sp) // android-changed: added sp.
 {
     register const struct ttinfo *  ttisp;
     register int            i;
@@ -1347,12 +1326,7 @@
             return result;
     }
     if (sp->timecnt == 0 || t < sp->ats[0]) {
-        i = 0;
-        while (sp->ttis[i].tt_isdst)
-            if (++i >= sp->typecnt) {
-                i = 0;
-                break;
-            }
+        i = sp->defaulttype;
     } else {
         register int    lo = 1;
         register int    hi = sp->timecnt;
@@ -1383,8 +1357,7 @@
 }
 
 struct tm *
-localtime(timep)
-const time_t * const    timep;
+localtime(const time_t * const timep)
 {
     return localtime_r(timep, &tmGlobal);
 }
@@ -1394,9 +1367,7 @@
 */
 
 struct tm *
-localtime_r(timep, tmp)
-const time_t * const    timep;
-struct tm *     tmp;
+localtime_r(const time_t * const timep, struct tm * tmp)
 {
     struct tm*  result;
 
@@ -1413,11 +1384,8 @@
 */
 
 static struct tm *
-gmtsub(timep, offset, tmp, sp) // android-changed: added sp.
-const time_t * const    timep;
-const long      offset;
-struct tm * const   tmp;
-const struct state * sp; // android-changed: added sp.
+gmtsub(const time_t * const timep, const int_fast32_t offset,
+       struct tm *const tmp, const struct state * sp) // android-changed: added sp.
 {
     register struct tm *    result;
 
@@ -1426,7 +1394,7 @@
     if (!gmt_is_set) {
         gmt_is_set = TRUE;
 #ifdef ALL_STATE
-        gmtptr = (struct state *) malloc(sizeof *gmtptr);
+        gmtptr = calloc(1, sizeof *gmtptr);
         if (gmtptr != NULL)
 #endif /* defined ALL_STATE */
             gmtload(gmtptr);
@@ -1455,8 +1423,7 @@
 }
 
 struct tm *
-gmtime(timep)
-const time_t * const    timep;
+gmtime(const time_t * const timep)
 {
     return gmtime_r(timep, &tmGlobal);
 }
@@ -1466,9 +1433,7 @@
 */
 
 struct tm *
-gmtime_r(timep, tmp)
-const time_t * const    timep;
-struct tm *     tmp;
+gmtime_r(const time_t * const timep, struct tm * tmp)
 {
     struct tm*  result;
 
@@ -1479,45 +1444,30 @@
     return result;
 }
 
-#ifdef STD_INSPIRED
-#if 0 /* disabled because there is no good documentation for this function */
-struct tm *
-offtime(timep, offset)
-const time_t * const    timep;
-const long      offset;
-{
-    return gmtsub(timep, offset, &tmGlobal, NULL); // android-changed: extra parameter.
-}
-#endif /* 0 */
-#endif /* defined STD_INSPIRED */
-
 /*
 ** Return the number of leap years through the end of the given year
 ** where, to make the math easy, the answer for year zero is defined as zero.
 */
 
 static int
-leaps_thru_end_of(y)
-register const int  y;
+leaps_thru_end_of(register const int y)
 {
     return (y >= 0) ? (y / 4 - y / 100 + y / 400) :
         -(leaps_thru_end_of(-(y + 1)) + 1);
 }
 
 static struct tm *
-timesub(timep, offset, sp, tmp)
-const time_t * const            timep;
-const long              offset;
-register const struct state * const sp;
-register struct tm * const      tmp;
+timesub(const time_t *const timep, const int_fast32_t offset,
+        register const struct state *const sp,
+        register struct tm *const tmp)
 {
     register const struct lsinfo *  lp;
     register time_t         tdays;
     register int            idays;  /* unsigned would be so 2003 */
-    register long           rem;
+    register int_fast64_t           rem;
     int             y;
     register const int *        ip;
-    register long           corr;
+    register int_fast64_t           corr;
     register int            hit;
     register int            i;
 
@@ -1574,9 +1524,10 @@
         y = newy;
     }
     {
-        register long   seconds;
+        register int_fast32_t   seconds;
+        register time_t half_second = 0.5;
 
-        seconds = tdays * SECSPERDAY + 0.5;
+        seconds = tdays * SECSPERDAY + half_second;
         tdays = seconds / SECSPERDAY;
         rem += seconds - tdays * SECSPERDAY;
     }
@@ -1639,8 +1590,7 @@
 }
 
 char *
-ctime(timep)
-const time_t * const    timep;
+ctime(const time_t * const timep)
 {
 /*
 ** Section 4.12.3.2 of X3.159-1989 requires that
@@ -1652,9 +1602,7 @@
 }
 
 char *
-ctime_r(timep, buf)
-const time_t * const    timep;
-char *          buf;
+ctime_r(const time_t * const timep, char * buf)
 {
     struct tm   mytm;
 
@@ -1675,77 +1623,65 @@
 #endif /* !defined WRONG */
 
 /*
-** Simplified normalize logic courtesy Paul Eggert.
+** Normalize logic courtesy Paul Eggert.
 */
 
 static int
-increment_overflow(number, delta)
-int *   number;
-int delta;
+increment_overflow(int *const ip, int j)
 {
-    unsigned  number0 = (unsigned)*number;
-    unsigned  number1 = (unsigned)(number0 + delta);
+	register int const	i = *ip;
 
-    *number = (int)number1;
-
-    if (delta >= 0) {
-        return ((int)number1 < (int)number0);
-    } else {
-        return ((int)number1 > (int)number0);
-    }
+	/*
+	** 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
-long_increment_overflow(number, delta)
-long *  number;
-int delta;
+increment_overflow32(int_fast32_t *const lp, int const m)
 {
-    unsigned long  number0 = (unsigned long)*number;
-    unsigned long  number1 = (unsigned long)(number0 + delta);
+	register int_fast32_t const	l = *lp;
 
-    *number = (long)number1;
-
-    if (delta >= 0) {
-        return ((long)number1 < (long)number0);
-    } else {
-        return ((long)number1 > (long)number0);
-    }
+	if ((l >= 0) ? (m > INT_FAST32_MAX - l) : (m < INT_FAST32_MIN - l))
+		return TRUE;
+	*lp += m;
+	return FALSE;
 }
 
 static int
-normalize_overflow(tensptr, unitsptr, base)
-int * const tensptr;
-int * const unitsptr;
-const int   base;
+normalize_overflow(int *const tensptr, int *const unitsptr, const int base)
 {
-    register int    tensdelta;
+	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 int
-long_normalize_overflow(tensptr, unitsptr, base)
-long * const    tensptr;
-int * const unitsptr;
-const int   base;
+normalize_overflow32(int_fast32_t *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 long_increment_overflow(tensptr, tensdelta);
+	tensdelta = (*unitsptr >= 0) ?
+		(*unitsptr / base) :
+		(-1 - (-1 - *unitsptr) / base);
+	*unitsptr -= tensdelta * base;
+	return increment_overflow32(tensptr, tensdelta);
 }
 
 static int
-tmcomp(atmp, btmp)
-register const struct tm * const atmp;
-register const struct tm * const btmp;
+tmcomp(register const struct tm * const atmp,
+       register const struct tm * const btmp)
 {
     register int    result;
 
@@ -1759,21 +1695,19 @@
 }
 
 static time_t
-time2sub(tmp, funcp, offset, okayp, do_norm_secs, sp) // android-changed: added sp
-struct tm * const   tmp;
-struct tm * (* const    funcp) P((const time_t*, long, struct tm*, const struct state*)); // android-changed: added state*
-const long      offset;
-int * const     okayp;
-const int       do_norm_secs;
-const struct state * sp; // android-changed: added sp
+time2sub(struct tm * const tmp,
+         struct tm *(*const funcp)(const time_t*, int_fast32_t, struct tm*, const struct state*),
+         const int_fast32_t offset,
+         int * const okayp,
+         const int do_norm_secs, const struct state * sp) // android-changed: added sp
 {
     register int            dir;
     register int            i, j;
     register int            saved_seconds;
-    register long           li;
+    register int_fast32_t           li;
     register time_t         lo;
     register time_t         hi;
-    long                y;
+    int_fast32_t                y;
     time_t              newt;
     time_t              t;
     struct tm           yourtm, mytm;
@@ -1790,16 +1724,16 @@
     if (normalize_overflow(&yourtm.tm_mday, &yourtm.tm_hour, HOURSPERDAY))
         return WRONG;
     y = yourtm.tm_year;
-    if (long_normalize_overflow(&y, &yourtm.tm_mon, MONSPERYEAR))
+    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 (long_increment_overflow(&y, TM_YEAR_BASE))
+    if (increment_overflow32(&y, TM_YEAR_BASE))
         return WRONG;
     while (yourtm.tm_mday <= 0) {
-        if (long_increment_overflow(&y, -1))
+        if (increment_overflow32(&y, -1))
             return WRONG;
         li = y + (1 < yourtm.tm_mon);
         yourtm.tm_mday += year_lengths[isleap(li)];
@@ -1807,7 +1741,7 @@
     while (yourtm.tm_mday > DAYSPERLYEAR) {
         li = y + (1 < yourtm.tm_mon);
         yourtm.tm_mday -= year_lengths[isleap(li)];
-        if (long_increment_overflow(&y, 1))
+        if (increment_overflow32(&y, 1))
             return WRONG;
     }
     for ( ; ; ) {
@@ -1817,11 +1751,11 @@
         yourtm.tm_mday -= i;
         if (++yourtm.tm_mon >= MONSPERYEAR) {
             yourtm.tm_mon = 0;
-            if (long_increment_overflow(&y, 1))
+            if (increment_overflow32(&y, 1))
                 return WRONG;
         }
     }
-    if (long_increment_overflow(&y, -TM_YEAR_BASE))
+    if (increment_overflow32(&y, -TM_YEAR_BASE))
         return WRONG;
     yourtm.tm_year = y;
     if (yourtm.tm_year != y)
@@ -1878,14 +1812,14 @@
         } else  dir = tmcomp(&mytm, &yourtm);
         if (dir != 0) {
             if (t == lo) {
-                if (t == TIME_T_MAX)
-                    return WRONG;
                 ++t;
+                if (t <= lo)
+                    return WRONG;
                 ++lo;
             } else if (t == hi) {
-                if (t == TIME_T_MIN)
-                    return WRONG;
                 --t;
+                if (t >= hi)
+                    return WRONG;
                 --hi;
             }
             if (lo > hi)
@@ -1903,14 +1837,10 @@
         ** It's okay to guess wrong since the guess
         ** gets checked.
         */
-        /*
-        ** The (void *) casts are the benefit of SunOS 3.3 on Sun 2's.
-        */
         // BEGIN android-changed: support user-supplied sp
         if (sp == NULL) {
             sp = (const struct state *)
-                (((void *) funcp == (void *) localsub) ?
-                lclptr : gmtptr);
+                ((funcp == localsub) ? lclptr : gmtptr);
         }
         // END android-changed
 #ifdef ALL_STATE
@@ -1950,14 +1880,11 @@
     return t;
 }
 
-// BEGIN android-changed: added sp.
 static time_t
-time2(tmp, funcp, offset, okayp, sp)
-struct tm * const   tmp;
-struct tm * (* const    funcp) P((const time_t*, long, struct tm*, const struct state*));
-const long      offset;
-int * const     okayp;
-const struct state * sp;
+time2(struct tm * const tmp,
+      struct tm * (*const funcp)(const time_t *, int_fast32_t, struct tm *, const struct state *), // android-changed: added sp.
+      const int_fast32_t offset,
+      int *const okayp, const struct state* sp) // android-changed: added sp.
 {
     time_t  t;
 
@@ -1969,14 +1896,11 @@
     t = time2sub(tmp, funcp, offset, okayp, FALSE, sp);
     return *okayp ? t : time2sub(tmp, funcp, offset, okayp, TRUE, sp);
 }
-// END android-changed
 
 static time_t
-time1(tmp, funcp, offset, sp) // android-changed: added sp.
-struct tm * const   tmp;
-struct tm * (* const    funcp) P((const time_t *, long, struct tm *, const struct state *));
-const long      offset;
-const struct state * sp; // android-changed: added sp.
+time1(struct tm * const tmp,
+      struct tm * (* const funcp) (const time_t *, int_fast32_t, struct tm *, const struct state *), // android-changed: added sp.
+      const int_fast32_t offset, const struct state * sp) // android-changed: added sp.
 {
     register time_t         t;
     register int            samei, otheri;
@@ -1987,6 +1911,10 @@
     int             types[TZ_MAX_TYPES];
     int             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.
@@ -2009,13 +1937,9 @@
     ** We try to divine the type they started from and adjust to the
     ** type they need.
     */
-    /*
-    ** The (void *) casts are the benefit of SunOS 3.3 on Sun 2's.
-    */
     // BEGIN android-changed: support user-supplied sp.
     if (sp == NULL) {
-        sp = (const struct state *) (((void *) funcp == (void *) localsub) ?
-            lclptr : gmtptr);
+        sp = (const struct state *) ((funcp == localsub) ?  lclptr : gmtptr);
     }
     // BEGIN android-changed
 #ifdef ALL_STATE
@@ -2053,86 +1977,32 @@
 }
 
 time_t
-mktime(tmp)
-struct tm * const   tmp;
+mktime(struct tm * const tmp)
 {
-    time_t  result;
     _tzLock();
     tzset_locked();
-    result = time1(tmp, localsub, 0L, NULL); // android-changed: extra parameter.
+    time_t result = time1(tmp, localsub, 0L, NULL); // android-changed: extra parameter.
     _tzUnlock();
     return result;
 }
 
-// BEGIN android-added
-
-// Caches the most recent timezone (http://b/8270865).
-static int __bionic_tzload_cached(const char* name, struct state* const sp, const int doextend) {
-  _tzLock();
-
-  // Our single-item cache.
-  static char* gCachedTimeZoneName;
-  static struct state gCachedTimeZone;
-
-  // Do we already have this timezone cached?
-  if (gCachedTimeZoneName != NULL && strcmp(name, gCachedTimeZoneName) == 0) {
-    *sp = gCachedTimeZone;
-    _tzUnlock();
-    return 0;
-  }
-
-  // Can we load it?
-  int rc = tzload(name, sp, doextend);
-  if (rc == 0) {
-    // Update the cache.
-    free(gCachedTimeZoneName);
-    gCachedTimeZoneName = strdup(name);
-    gCachedTimeZone = *sp;
-  }
-
-  _tzUnlock();
-  return rc;
-}
-
-// Non-standard API: mktime(3) but with an explicit timezone parameter.
-time_t mktime_tz(struct tm* const tmp, const char* tz) {
-  struct state st;
-  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 time1(tmp, localsub, 0L, &st);
-}
-
-// Non-standard API: localtime(3) but with an explicit timezone parameter.
-void localtime_tz(const time_t* const timep, struct tm* tmp, const char* tz) {
-  struct state st;
-  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);
-  }
-  localsub(timep, 0L, tmp, &st);
-}
-
-// END android-added
-
 #ifdef STD_INSPIRED
 
 time_t
-timelocal(tmp)
-struct tm * const   tmp;
+timelocal(struct tm * const tmp)
 {
-    tmp->tm_isdst = -1; /* in case it wasn't initialized */
+    if (tmp != NULL)
+        tmp->tm_isdst = -1; /* in case it wasn't initialized */
     return mktime(tmp);
 }
 
 time_t
-timegm(tmp)
-struct tm * const   tmp;
+timegm(struct tm * const tmp)
 {
     time_t  result;
 
-    tmp->tm_isdst = 0;
+    if (tmp != NULL)
+        tmp->tm_isdst = 0;
     _tzLock();
     result = time1(tmp, gmtsub, 0L, NULL); // android-changed: extra parameter.
     _tzUnlock();
@@ -2140,23 +2010,6 @@
     return result;
 }
 
-#if 0 /* disable due to lack of clear documentation on this function */
-time_t
-timeoff(tmp, offset)
-struct tm * const   tmp;
-const long      offset;
-{
-    time_t  result;
-
-    tmp->tm_isdst = 0;
-    _tzLock();
-    result = time1(tmp, gmtsub, offset, NULL); // android-changed: extra parameter.
-    _tzUnlock();
-
-    return result;
-}
-#endif /* 0 */
-
 #endif /* defined STD_INSPIRED */
 
 #ifdef CMUCS
@@ -2166,9 +2019,8 @@
 ** previous versions of the CMUCS runtime library.
 */
 
-long
-gtime(tmp)
-struct tm * const   tmp;
+int_fast32_t
+gtime(struct tm * const tmp)
 {
     const time_t    t = mktime(tmp);
 
@@ -2193,9 +2045,8 @@
 ** when exchanging timestamps with POSIX conforming systems.
 */
 
-static long
-leapcorr(timep)
-time_t *    timep;
+static int_fast64_t
+leapcorr(time_t * timep)
 {
     register struct state *     sp;
     register struct lsinfo *    lp;
@@ -2212,16 +2063,14 @@
 }
 
 time_t
-time2posix(t)
-time_t  t;
+time2posix(time_t t)
 {
     tzset();
     return t - leapcorr(&t);
 }
 
 time_t
-posix2time(t)
-time_t  t;
+posix2time(time_t t)
 {
     time_t  x;
     time_t  y;
@@ -2255,10 +2104,16 @@
 
 #endif /* defined STD_INSPIRED */
 
+// BEGIN android-added
+
 #include <assert.h>
 #include <stdint.h>
 #include <arpa/inet.h> // For ntohl(3).
 
+static int to_int(unsigned char* s) {
+  return (s[0] << 24) | (s[1] << 16) | (s[2] << 8) | s[3];
+}
+
 static int __bionic_open_tzdata_path(const char* path, const char* olson_id, int* data_size) {
   int fd = TEMP_FAILURE_RETRY(open(path, OPEN_MODE));
   if (fd == -1) {
@@ -2322,8 +2177,8 @@
     this_id[NAME_LENGTH] = '\0';
 
     if (strcmp(this_id, olson_id) == 0) {
-      specific_zone_offset = toint(buf + NAME_LENGTH) + ntohl(header.data_offset);
-      *data_size = toint(buf + NAME_LENGTH + sizeof(int32_t));
+      specific_zone_offset = to_int(buf + NAME_LENGTH) + ntohl(header.data_offset);
+      *data_size = to_int(buf + NAME_LENGTH + sizeof(int32_t));
       break;
     }
   }
@@ -2359,3 +2214,53 @@
   }
   return fd;
 }
+
+// Caches the most recent timezone (http://b/8270865).
+static int __bionic_tzload_cached(const char* name, struct state* const sp, const int doextend) {
+  _tzLock();
+
+  // Our single-item cache.
+  static char* gCachedTimeZoneName;
+  static struct state gCachedTimeZone;
+
+  // Do we already have this timezone cached?
+  if (gCachedTimeZoneName != NULL && strcmp(name, gCachedTimeZoneName) == 0) {
+    *sp = gCachedTimeZone;
+    _tzUnlock();
+    return 0;
+  }
+
+  // Can we load it?
+  int rc = tzload(name, sp, doextend);
+  if (rc == 0) {
+    // Update the cache.
+    free(gCachedTimeZoneName);
+    gCachedTimeZoneName = strdup(name);
+    gCachedTimeZone = *sp;
+  }
+
+  _tzUnlock();
+  return rc;
+}
+
+// Non-standard API: mktime(3) but with an explicit timezone parameter.
+time_t mktime_tz(struct tm* const tmp, const char* tz) {
+  struct state st;
+  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 time1(tmp, localsub, 0L, &st);
+}
+
+// Non-standard API: localtime(3) but with an explicit timezone parameter.
+void localtime_tz(const time_t* const timep, struct tm* tmp, const char* tz) {
+  struct state st;
+  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);
+  }
+  localsub(timep, 0L, tmp, &st);
+}
+
+// END android-added