Home | History | Annotate | Download | only in libcutils
      1 /*
      2 ** This file is in the public domain, so clarified as of
      3 ** 1996-06-05 by Arthur David Olson.
      4 */
      5 
      6 #include <stdio.h>
      7 
      8 #ifndef lint
      9 #ifndef NOID
     10 static char	elsieid[] = "@(#)localtime.c	8.3";
     11 #endif /* !defined NOID */
     12 #endif /* !defined lint */
     13 
     14 /*
     15 ** Leap second handling from Bradley White.
     16 ** POSIX-style TZ environment variable handling from Guy Harris.
     17 */
     18 
     19 /*LINTLIBRARY*/
     20 
     21 #include "private.h"
     22 #include "tzfile.h"
     23 #include "fcntl.h"
     24 #include "float.h"	/* for FLT_MAX and DBL_MAX */
     25 
     26 #ifndef TZ_ABBR_MAX_LEN
     27 #define TZ_ABBR_MAX_LEN	16
     28 #endif /* !defined TZ_ABBR_MAX_LEN */
     29 
     30 #ifndef TZ_ABBR_CHAR_SET
     31 #define TZ_ABBR_CHAR_SET \
     32 	"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 :+-._"
     33 #endif /* !defined TZ_ABBR_CHAR_SET */
     34 
     35 #ifndef TZ_ABBR_ERR_CHAR
     36 #define TZ_ABBR_ERR_CHAR	'_'
     37 #endif /* !defined TZ_ABBR_ERR_CHAR */
     38 
     39 #define INDEXFILE "/system/usr/share/zoneinfo/zoneinfo.idx"
     40 #define DATAFILE "/system/usr/share/zoneinfo/zoneinfo.dat"
     41 #define NAMELEN 40
     42 #define INTLEN 4
     43 #define READLEN (NAMELEN + 3 * INTLEN)
     44 
     45 /*
     46 ** SunOS 4.1.1 headers lack O_BINARY.
     47 */
     48 
     49 #ifdef O_BINARY
     50 #define OPEN_MODE	(O_RDONLY | O_BINARY)
     51 #endif /* defined O_BINARY */
     52 #ifndef O_BINARY
     53 #define OPEN_MODE	O_RDONLY
     54 #endif /* !defined O_BINARY */
     55 
     56 /* Complex computations to determine the min/max of time_t depending
     57  * on TYPE_BIT / TYPE_SIGNED / TYPE_INTEGRAL.
     58  * These macros cannot be used in pre-processor directives, so we
     59  * let the C compiler do the work, which makes things a bit funky.
     60  */
     61 static const time_t TIME_T_MAX =
     62     TYPE_INTEGRAL(time_t) ?
     63         ( TYPE_SIGNED(time_t) ?
     64             ~((time_t)1 << (TYPE_BIT(time_t)-1))
     65         :
     66             ~(time_t)0
     67         )
     68     : /* if time_t is a floating point number */
     69         ( sizeof(time_t) > sizeof(float) ? (time_t)DBL_MAX : (time_t)FLT_MAX );
     70 
     71 static const time_t TIME_T_MIN =
     72     TYPE_INTEGRAL(time_t) ?
     73         ( TYPE_SIGNED(time_t) ?
     74             ((time_t)1 << (TYPE_BIT(time_t)-1))
     75         :
     76             0
     77         )
     78     :
     79         ( sizeof(time_t) > sizeof(float) ? (time_t)DBL_MIN : (time_t)FLT_MIN );
     80 
     81 #ifndef WILDABBR
     82 /*
     83 ** Someone might make incorrect use of a time zone abbreviation:
     84 **	1.	They might reference tzname[0] before calling tzset (explicitly
     85 **		or implicitly).
     86 **	2.	They might reference tzname[1] before calling tzset (explicitly
     87 **		or implicitly).
     88 **	3.	They might reference tzname[1] after setting to a time zone
     89 **		in which Daylight Saving Time is never observed.
     90 **	4.	They might reference tzname[0] after setting to a time zone
     91 **		in which Standard Time is never observed.
     92 **	5.	They might reference tm.TM_ZONE after calling offtime.
     93 ** What's best to do in the above cases is open to debate;
     94 ** for now, we just set things up so that in any of the five cases
     95 ** WILDABBR is used. Another possibility: initialize tzname[0] to the
     96 ** string "tzname[0] used before set", and similarly for the other cases.
     97 ** And another: initialize tzname[0] to "ERA", with an explanation in the
     98 ** manual page of what this "time zone abbreviation" means (doing this so
     99 ** that tzname[0] has the "normal" length of three characters).
    100 */
    101 #define WILDABBR	"   "
    102 #endif /* !defined WILDABBR */
    103 
    104 static char		wildabbr[] = WILDABBR;
    105 
    106 static const char	gmt[] = "GMT";
    107 
    108 /*
    109 ** The DST rules to use if TZ has no rules and we can't load TZDEFRULES.
    110 ** We default to US rules as of 1999-08-17.
    111 ** POSIX 1003.1 section 8.1.1 says that the default DST rules are
    112 ** implementation dependent; for historical reasons, US rules are a
    113 ** common default.
    114 */
    115 #ifndef TZDEFRULESTRING
    116 #define TZDEFRULESTRING ",M4.1.0,M10.5.0"
    117 #endif /* !defined TZDEFDST */
    118 
    119 struct ttinfo {				/* time type information */
    120 	long		tt_gmtoff;	/* UTC offset in seconds */
    121 	int		tt_isdst;	/* used to set tm_isdst */
    122 	int		tt_abbrind;	/* abbreviation list index */
    123 	int		tt_ttisstd;	/* TRUE if transition is std time */
    124 	int		tt_ttisgmt;	/* TRUE if transition is UTC */
    125 };
    126 
    127 struct lsinfo {				/* leap second information */
    128 	time_t		ls_trans;	/* transition time */
    129 	long		ls_corr;	/* correction to apply */
    130 };
    131 
    132 #define BIGGEST(a, b)	(((a) > (b)) ? (a) : (b))
    133 
    134 #ifdef TZNAME_MAX
    135 #define MY_TZNAME_MAX	TZNAME_MAX
    136 #endif /* defined TZNAME_MAX */
    137 #ifndef TZNAME_MAX
    138 #define MY_TZNAME_MAX	255
    139 #endif /* !defined TZNAME_MAX */
    140 
    141 struct state {
    142 	int		leapcnt;
    143 	int		timecnt;
    144 	int		typecnt;
    145 	int		charcnt;
    146 	int		goback;
    147 	int		goahead;
    148 	time_t		ats[TZ_MAX_TIMES];
    149 	unsigned char	types[TZ_MAX_TIMES];
    150 	struct ttinfo	ttis[TZ_MAX_TYPES];
    151 	char		chars[BIGGEST(BIGGEST(TZ_MAX_CHARS + 1, sizeof gmt),
    152 				(2 * (MY_TZNAME_MAX + 1)))];
    153 	struct lsinfo	lsis[TZ_MAX_LEAPS];
    154 };
    155 
    156 struct rule {
    157 	int		r_type;		/* type of rule--see below */
    158 	int		r_day;		/* day number of rule */
    159 	int		r_week;		/* week number of rule */
    160 	int		r_mon;		/* month number of rule */
    161 	long		r_time;		/* transition time of rule */
    162 };
    163 
    164 #define JULIAN_DAY		0	/* Jn - Julian day */
    165 #define DAY_OF_YEAR		1	/* n - day of year */
    166 #define MONTH_NTH_DAY_OF_WEEK	2	/* Mm.n.d - month, week, day of week */
    167 
    168 /*
    169 ** Prototypes for static functions.
    170 */
    171 
    172 static long		detzcode P((const char * codep));
    173 static time_t		detzcode64 P((const char * codep));
    174 static int		differ_by_repeat P((time_t t1, time_t t0));
    175 static const char *	getzname P((const char * strp));
    176 static const char *	getqzname P((const char * strp, const int delim));
    177 static const char *	getnum P((const char * strp, int * nump, int min,
    178 				int max));
    179 static const char *	getsecs P((const char * strp, long * secsp));
    180 static const char *	getoffset P((const char * strp, long * offsetp));
    181 static const char *	getrule P((const char * strp, struct rule * rulep));
    182 static void		gmtload P((struct state * sp));
    183 static struct tm *	gmtsub P((const time_t * timep, long offset,
    184 				struct tm * tmp));
    185 static struct tm *	localsub P((const time_t * timep, long offset,
    186 				struct tm * tmp, const struct state *sp));
    187 static int		increment_overflow P((int * number, int delta));
    188 static int		leaps_thru_end_of P((int y));
    189 static int		long_increment_overflow P((long * number, int delta));
    190 static int		long_normalize_overflow P((long * tensptr,
    191 				int * unitsptr, int base));
    192 static int		normalize_overflow P((int * tensptr, int * unitsptr,
    193 				int base));
    194 static void		settzname P((void));
    195 static time_t		time1 P((struct tm * tmp,
    196 				struct tm * (*funcp) P((const time_t *,
    197 				long, struct tm *, const struct state* sp)),
    198 				long offset, const struct state *	sp));
    199 static time_t		time2 P((struct tm *tmp,
    200 				struct tm * (*funcp) P((const time_t *,
    201 				long, struct tm*, const struct state* sp)),
    202 				long offset, int * okayp, const struct state *	sp));
    203 static time_t		time2sub P((struct tm *tmp,
    204 				struct tm * (*funcp) P((const time_t*, long, struct tm*,const struct state *sp)),
    205 				long offset, int * okayp, int do_norm_secs,
    206                 const struct state *sp));
    207 static struct tm *	timesub P((const time_t * timep, long offset,
    208 				const struct state * sp, struct tm * tmp));
    209 static int		tmcomp P((const struct tm * atmp,
    210 				const struct tm * btmp));
    211 static time_t		transtime P((time_t janfirst, int year,
    212 				const struct rule * rulep, long offset));
    213 static int		tzload P((const char * name, struct state * sp,
    214 				int doextend));
    215 static int		tzload_uncached P((const char * name, struct state * sp,
    216 				int doextend));
    217 static int		tzparse P((const char * name, struct state * sp,
    218 				int lastditch));
    219 
    220 #ifdef ALL_STATE
    221 static struct state *	gmtptr;
    222 #endif /* defined ALL_STATE */
    223 
    224 #ifndef ALL_STATE
    225 static struct state	gmtmem;
    226 #define gmtptr		(&gmtmem)
    227 #endif /* State Farm */
    228 
    229 #define CACHE_COUNT 4
    230 static char * g_cacheNames[CACHE_COUNT] = {0,0};
    231 static struct state	g_cacheStates[CACHE_COUNT];
    232 static int g_lastCache = 0;
    233 static struct state g_utc;
    234 unsigned char g_utcSet = 0;
    235 
    236 
    237 #ifndef TZ_STRLEN_MAX
    238 #define TZ_STRLEN_MAX 255
    239 #endif /* !defined TZ_STRLEN_MAX */
    240 
    241 static char		lcl_TZname[TZ_STRLEN_MAX + 1];
    242 static int		lcl_is_set;
    243 static int		gmt_is_set;
    244 
    245 char *			tzname[2] = {
    246 	wildabbr,
    247 	wildabbr
    248 };
    249 
    250 /*
    251 ** Section 4.12.3 of X3.159-1989 requires that
    252 **	Except for the strftime function, these functions [asctime,
    253 **	ctime, gmtime, localtime] return values in one of two static
    254 **	objects: a broken-down time structure and an array of char.
    255 ** Thanks to Paul Eggert for noting this.
    256 */
    257 
    258 static struct tm	tm;
    259 
    260 #ifdef USG_COMPAT
    261 time_t			timezone = 0;
    262 int			daylight = 0;
    263 #endif /* defined USG_COMPAT */
    264 
    265 #ifdef ALTZONE
    266 time_t			altzone = 0;
    267 #endif /* defined ALTZONE */
    268 
    269 static long
    270 detzcode(codep)
    271 const char * const	codep;
    272 {
    273 	register long	result;
    274 	register int	i;
    275 
    276 	result = (codep[0] & 0x80) ? ~0L : 0;
    277 	for (i = 0; i < 4; ++i)
    278 		result = (result << 8) | (codep[i] & 0xff);
    279 	return result;
    280 }
    281 
    282 static time_t
    283 detzcode64(codep)
    284 const char * const	codep;
    285 {
    286 	register time_t	result;
    287 	register int	i;
    288 
    289 	result = (codep[0] & 0x80) ?  (~(int_fast64_t) 0) : 0;
    290 	for (i = 0; i < 8; ++i)
    291 		result = result * 256 + (codep[i] & 0xff);
    292 	return result;
    293 }
    294 
    295 static int
    296 differ_by_repeat(t1, t0)
    297 const time_t	t1;
    298 const time_t	t0;
    299 {
    300 	if (TYPE_INTEGRAL(time_t) &&
    301 		TYPE_BIT(time_t) - TYPE_SIGNED(time_t) < SECSPERREPEAT_BITS)
    302 			return 0;
    303 	return t1 - t0 == SECSPERREPEAT;
    304 }
    305 
    306 static int toint(unsigned char *s) {
    307     return (s[0] << 24) | (s[1] << 16) | (s[2] << 8) | s[3];
    308 }
    309 
    310 static int
    311 tzload(const char *name, struct state * const sp, const int doextend)
    312 {
    313     if (name) {
    314         int i, err;
    315         if (0 == strcmp(name, "UTC")) {
    316             if (!g_utcSet) {
    317                 tzload_uncached(name, &g_utc, 1);
    318                 g_utcSet = 1;
    319             }
    320             //printf("tzload: utc\n");
    321             *sp = g_utc;
    322             return 0;
    323         }
    324         for (i=0; i<CACHE_COUNT; i++) {
    325             if (g_cacheNames[i] && 0 == strcmp(name, g_cacheNames[i])) {
    326                 *sp = g_cacheStates[i];
    327                 //printf("tzload: hit: %s\n", name);
    328                 return 0;
    329             }
    330         }
    331         //printf("tzload: miss: %s\n", name);
    332         g_lastCache++;
    333         if (g_lastCache >= CACHE_COUNT) {
    334             g_lastCache = 0;
    335         }
    336         i = g_lastCache;
    337         if (g_cacheNames[i]) {
    338             free(g_cacheNames[i]);
    339         }
    340         err = tzload_uncached(name, &(g_cacheStates[i]), 1);
    341         if (err == 0) {
    342             g_cacheNames[i] = strdup(name);
    343             *sp = g_cacheStates[i];
    344             return 0;
    345         } else {
    346             g_cacheNames[i] = NULL;
    347             return err;
    348         }
    349     }
    350     return tzload_uncached(name, sp, doextend);
    351 }
    352 
    353 static int
    354 tzload_uncached(name, sp, doextend)
    355 register const char *		name;
    356 register struct state * const	sp;
    357 register const int		doextend;
    358 {
    359 	register const char *		p;
    360 	register int			i;
    361 	register int			fid;
    362 	register int			stored;
    363 	register int			nread;
    364 	union {
    365 		struct tzhead	tzhead;
    366 		char		buf[2 * sizeof(struct tzhead) +
    367 					2 * sizeof *sp +
    368 					4 * TZ_MAX_TIMES];
    369 	} u;
    370     int                     toread = sizeof u.buf;
    371 
    372 	if (name == NULL && (name = TZDEFAULT) == NULL)
    373 		return -1;
    374 	{
    375 		register int	doaccess;
    376 		/*
    377 		** Section 4.9.1 of the C standard says that
    378 		** "FILENAME_MAX expands to an integral constant expression
    379 		** that is the size needed for an array of char large enough
    380 		** to hold the longest file name string that the implementation
    381 		** guarantees can be opened."
    382 		*/
    383 		char		fullname[FILENAME_MAX + 1];
    384 		const char	*origname = name;
    385 
    386 		if (name[0] == ':')
    387 			++name;
    388 		doaccess = name[0] == '/';
    389 		if (!doaccess) {
    390 			if ((p = TZDIR) == NULL)
    391 				return -1;
    392 			if ((strlen(p) + strlen(name) + 1) >= sizeof fullname)
    393 				return -1;
    394 			(void) strcpy(fullname, p);
    395 			(void) strcat(fullname, "/");
    396 			(void) strcat(fullname, name);
    397 			/*
    398 			** Set doaccess if '.' (as in "../") shows up in name.
    399 			*/
    400 			if (strchr(name, '.') != NULL)
    401 				doaccess = TRUE;
    402 			name = fullname;
    403 		}
    404 		if (doaccess && access(name, R_OK) != 0)
    405 			return -1;
    406 		if ((fid = open(name, OPEN_MODE)) == -1) {
    407             char buf[READLEN];
    408             char name[NAMELEN + 1];
    409             int fidix = open(INDEXFILE, OPEN_MODE);
    410             int off = -1;
    411 
    412             if (fidix < 0) {
    413                 return -1;
    414             }
    415 
    416             while (read(fidix, buf, sizeof(buf)) == sizeof(buf)) {
    417                 memcpy(name, buf, NAMELEN);
    418                 name[NAMELEN] = '\0';
    419 
    420                 if (strcmp(name, origname) == 0) {
    421                     off = toint((unsigned char *) buf + NAMELEN);
    422                     toread = toint((unsigned char *) buf + NAMELEN + INTLEN);
    423                     break;
    424                 }
    425             }
    426 
    427             close(fidix);
    428 
    429             if (off < 0)
    430                 return -1;
    431 
    432             fid = open(DATAFILE, OPEN_MODE);
    433 
    434             if (fid < 0) {
    435                 return -1;
    436             }
    437 
    438             if (lseek(fid, off, SEEK_SET) < 0) {
    439                 return -1;
    440             }
    441         }
    442 	}
    443 	nread = read(fid, u.buf, toread);
    444 	if (close(fid) < 0 || nread <= 0)
    445 		return -1;
    446 	for (stored = 4; stored <= 8; stored *= 2) {
    447 		int		ttisstdcnt;
    448 		int		ttisgmtcnt;
    449 
    450 		ttisstdcnt = (int) detzcode(u.tzhead.tzh_ttisstdcnt);
    451 		ttisgmtcnt = (int) detzcode(u.tzhead.tzh_ttisgmtcnt);
    452 		sp->leapcnt = (int) detzcode(u.tzhead.tzh_leapcnt);
    453 		sp->timecnt = (int) detzcode(u.tzhead.tzh_timecnt);
    454 		sp->typecnt = (int) detzcode(u.tzhead.tzh_typecnt);
    455 		sp->charcnt = (int) detzcode(u.tzhead.tzh_charcnt);
    456 		p = u.tzhead.tzh_charcnt + sizeof u.tzhead.tzh_charcnt;
    457 		if (sp->leapcnt < 0 || sp->leapcnt > TZ_MAX_LEAPS ||
    458 			sp->typecnt <= 0 || sp->typecnt > TZ_MAX_TYPES ||
    459 			sp->timecnt < 0 || sp->timecnt > TZ_MAX_TIMES ||
    460 			sp->charcnt < 0 || sp->charcnt > TZ_MAX_CHARS ||
    461 			(ttisstdcnt != sp->typecnt && ttisstdcnt != 0) ||
    462 			(ttisgmtcnt != sp->typecnt && ttisgmtcnt != 0))
    463 				return -1;
    464 		if (nread - (p - u.buf) <
    465 			sp->timecnt * stored +		/* ats */
    466 			sp->timecnt +			/* types */
    467 			sp->typecnt * 6 +		/* ttinfos */
    468 			sp->charcnt +			/* chars */
    469 			sp->leapcnt * (stored + 4) +	/* lsinfos */
    470 			ttisstdcnt +			/* ttisstds */
    471 			ttisgmtcnt)			/* ttisgmts */
    472 				return -1;
    473 		for (i = 0; i < sp->timecnt; ++i) {
    474 			sp->ats[i] = (stored == 4) ?
    475 				detzcode(p) : detzcode64(p);
    476 			p += stored;
    477 		}
    478 		for (i = 0; i < sp->timecnt; ++i) {
    479 			sp->types[i] = (unsigned char) *p++;
    480 			if (sp->types[i] >= sp->typecnt)
    481 				return -1;
    482 		}
    483 		for (i = 0; i < sp->typecnt; ++i) {
    484 			register struct ttinfo *	ttisp;
    485 
    486 			ttisp = &sp->ttis[i];
    487 			ttisp->tt_gmtoff = detzcode(p);
    488 			p += 4;
    489 			ttisp->tt_isdst = (unsigned char) *p++;
    490 			if (ttisp->tt_isdst != 0 && ttisp->tt_isdst != 1)
    491 				return -1;
    492 			ttisp->tt_abbrind = (unsigned char) *p++;
    493 			if (ttisp->tt_abbrind < 0 ||
    494 				ttisp->tt_abbrind > sp->charcnt)
    495 					return -1;
    496 		}
    497 		for (i = 0; i < sp->charcnt; ++i)
    498 			sp->chars[i] = *p++;
    499 		sp->chars[i] = '\0';	/* ensure '\0' at end */
    500 		for (i = 0; i < sp->leapcnt; ++i) {
    501 			register struct lsinfo *	lsisp;
    502 
    503 			lsisp = &sp->lsis[i];
    504 			lsisp->ls_trans = (stored == 4) ?
    505 				detzcode(p) : detzcode64(p);
    506 			p += stored;
    507 			lsisp->ls_corr = detzcode(p);
    508 			p += 4;
    509 		}
    510 		for (i = 0; i < sp->typecnt; ++i) {
    511 			register struct ttinfo *	ttisp;
    512 
    513 			ttisp = &sp->ttis[i];
    514 			if (ttisstdcnt == 0)
    515 				ttisp->tt_ttisstd = FALSE;
    516 			else {
    517 				ttisp->tt_ttisstd = *p++;
    518 				if (ttisp->tt_ttisstd != TRUE &&
    519 					ttisp->tt_ttisstd != FALSE)
    520 						return -1;
    521 			}
    522 		}
    523 		for (i = 0; i < sp->typecnt; ++i) {
    524 			register struct ttinfo *	ttisp;
    525 
    526 			ttisp = &sp->ttis[i];
    527 			if (ttisgmtcnt == 0)
    528 				ttisp->tt_ttisgmt = FALSE;
    529 			else {
    530 				ttisp->tt_ttisgmt = *p++;
    531 				if (ttisp->tt_ttisgmt != TRUE &&
    532 					ttisp->tt_ttisgmt != FALSE)
    533 						return -1;
    534 			}
    535 		}
    536 		/*
    537 		** Out-of-sort ats should mean we're running on a
    538 		** signed time_t system but using a data file with
    539 		** unsigned values (or vice versa).
    540 		*/
    541 		for (i = 0; i < sp->timecnt - 2; ++i)
    542 			if (sp->ats[i] > sp->ats[i + 1]) {
    543 				++i;
    544 				if (TYPE_SIGNED(time_t)) {
    545 					/*
    546 					** Ignore the end (easy).
    547 					*/
    548 					sp->timecnt = i;
    549 				} else {
    550 					/*
    551 					** Ignore the beginning (harder).
    552 					*/
    553 					register int	j;
    554 
    555 					for (j = 0; j + i < sp->timecnt; ++j) {
    556 						sp->ats[j] = sp->ats[j + i];
    557 						sp->types[j] = sp->types[j + i];
    558 					}
    559 					sp->timecnt = j;
    560 				}
    561 				break;
    562 			}
    563 		/*
    564 		** If this is an old file, we're done.
    565 		*/
    566 		if (u.tzhead.tzh_version[0] == '\0')
    567 			break;
    568 		nread -= p - u.buf;
    569 		for (i = 0; i < nread; ++i)
    570 			u.buf[i] = p[i];
    571 		/*
    572 		** If this is a narrow integer time_t system, we're done.
    573 		*/
    574 		if (stored >= (int) sizeof(time_t) && TYPE_INTEGRAL(time_t))
    575 			break;
    576 	}
    577 	if (doextend && nread > 2 &&
    578 		u.buf[0] == '\n' && u.buf[nread - 1] == '\n' &&
    579 		sp->typecnt + 2 <= TZ_MAX_TYPES) {
    580 			struct state	ts;
    581 			register int	result;
    582 
    583 			u.buf[nread - 1] = '\0';
    584 			result = tzparse(&u.buf[1], &ts, FALSE);
    585 			if (result == 0 && ts.typecnt == 2 &&
    586 				sp->charcnt + ts.charcnt <= TZ_MAX_CHARS) {
    587 					for (i = 0; i < 2; ++i)
    588 						ts.ttis[i].tt_abbrind +=
    589 							sp->charcnt;
    590 					for (i = 0; i < ts.charcnt; ++i)
    591 						sp->chars[sp->charcnt++] =
    592 							ts.chars[i];
    593 					i = 0;
    594 					while (i < ts.timecnt &&
    595 						ts.ats[i] <=
    596 						sp->ats[sp->timecnt - 1])
    597 							++i;
    598 					while (i < ts.timecnt &&
    599 					    sp->timecnt < TZ_MAX_TIMES) {
    600 						sp->ats[sp->timecnt] =
    601 							ts.ats[i];
    602 						sp->types[sp->timecnt] =
    603 							sp->typecnt +
    604 							ts.types[i];
    605 						++sp->timecnt;
    606 						++i;
    607 					}
    608 					sp->ttis[sp->typecnt++] = ts.ttis[0];
    609 					sp->ttis[sp->typecnt++] = ts.ttis[1];
    610 			}
    611 	}
    612 	i = 2 * YEARSPERREPEAT;
    613 	sp->goback = sp->goahead = sp->timecnt > i;
    614 	sp->goback &= sp->types[i] == sp->types[0] &&
    615 		differ_by_repeat(sp->ats[i], sp->ats[0]);
    616 	sp->goahead &=
    617 		sp->types[sp->timecnt - 1] == sp->types[sp->timecnt - 1 - i] &&
    618 		differ_by_repeat(sp->ats[sp->timecnt - 1],
    619 			 sp->ats[sp->timecnt - 1 - i]);
    620 	return 0;
    621 }
    622 
    623 static const int	mon_lengths[2][MONSPERYEAR] = {
    624 	{ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
    625 	{ 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
    626 };
    627 
    628 static const int	year_lengths[2] = {
    629 	DAYSPERNYEAR, DAYSPERLYEAR
    630 };
    631 
    632 /*
    633 ** Given a pointer into a time zone string, scan until a character that is not
    634 ** a valid character in a zone name is found. Return a pointer to that
    635 ** character.
    636 */
    637 
    638 static const char *
    639 getzname(strp)
    640 register const char *	strp;
    641 {
    642 	register char	c;
    643 
    644 	while ((c = *strp) != '\0' && !is_digit(c) && c != ',' && c != '-' &&
    645 		c != '+')
    646 			++strp;
    647 	return strp;
    648 }
    649 
    650 /*
    651 ** Given a pointer into an extended time zone string, scan until the ending
    652 ** delimiter of the zone name is located. Return a pointer to the delimiter.
    653 **
    654 ** As with getzname above, the legal character set is actually quite
    655 ** restricted, with other characters producing undefined results.
    656 ** We don't do any checking here; checking is done later in common-case code.
    657 */
    658 
    659 static const char *
    660 getqzname(register const char *strp, const int delim)
    661 {
    662 	register int	c;
    663 
    664 	while ((c = *strp) != '\0' && c != delim)
    665 		++strp;
    666 	return strp;
    667 }
    668 
    669 /*
    670 ** Given a pointer into a time zone string, extract a number from that string.
    671 ** Check that the number is within a specified range; if it is not, return
    672 ** NULL.
    673 ** Otherwise, return a pointer to the first character not part of the number.
    674 */
    675 
    676 static const char *
    677 getnum(strp, nump, min, max)
    678 register const char *	strp;
    679 int * const		nump;
    680 const int		min;
    681 const int		max;
    682 {
    683 	register char	c;
    684 	register int	num;
    685 
    686 	if (strp == NULL || !is_digit(c = *strp))
    687 		return NULL;
    688 	num = 0;
    689 	do {
    690 		num = num * 10 + (c - '0');
    691 		if (num > max)
    692 			return NULL;	/* illegal value */
    693 		c = *++strp;
    694 	} while (is_digit(c));
    695 	if (num < min)
    696 		return NULL;		/* illegal value */
    697 	*nump = num;
    698 	return strp;
    699 }
    700 
    701 /*
    702 ** Given a pointer into a time zone string, extract a number of seconds,
    703 ** in hh[:mm[:ss]] form, from the string.
    704 ** If any error occurs, return NULL.
    705 ** Otherwise, return a pointer to the first character not part of the number
    706 ** of seconds.
    707 */
    708 
    709 static const char *
    710 getsecs(strp, secsp)
    711 register const char *	strp;
    712 long * const		secsp;
    713 {
    714 	int	num;
    715 
    716 	/*
    717 	** `HOURSPERDAY * DAYSPERWEEK - 1' allows quasi-Posix rules like
    718 	** "M10.4.6/26", which does not conform to Posix,
    719 	** but which specifies the equivalent of
    720 	** ``02:00 on the first Sunday on or after 23 Oct''.
    721 	*/
    722 	strp = getnum(strp, &num, 0, HOURSPERDAY * DAYSPERWEEK - 1);
    723 	if (strp == NULL)
    724 		return NULL;
    725 	*secsp = num * (long) SECSPERHOUR;
    726 	if (*strp == ':') {
    727 		++strp;
    728 		strp = getnum(strp, &num, 0, MINSPERHOUR - 1);
    729 		if (strp == NULL)
    730 			return NULL;
    731 		*secsp += num * SECSPERMIN;
    732 		if (*strp == ':') {
    733 			++strp;
    734 			/* `SECSPERMIN' allows for leap seconds. */
    735 			strp = getnum(strp, &num, 0, SECSPERMIN);
    736 			if (strp == NULL)
    737 				return NULL;
    738 			*secsp += num;
    739 		}
    740 	}
    741 	return strp;
    742 }
    743 
    744 /*
    745 ** Given a pointer into a time zone string, extract an offset, in
    746 ** [+-]hh[:mm[:ss]] form, from the string.
    747 ** If any error occurs, return NULL.
    748 ** Otherwise, return a pointer to the first character not part of the time.
    749 */
    750 
    751 static const char *
    752 getoffset(strp, offsetp)
    753 register const char *	strp;
    754 long * const		offsetp;
    755 {
    756 	register int	neg = 0;
    757 
    758 	if (*strp == '-') {
    759 		neg = 1;
    760 		++strp;
    761 	} else if (*strp == '+')
    762 		++strp;
    763 	strp = getsecs(strp, offsetp);
    764 	if (strp == NULL)
    765 		return NULL;		/* illegal time */
    766 	if (neg)
    767 		*offsetp = -*offsetp;
    768 	return strp;
    769 }
    770 
    771 /*
    772 ** Given a pointer into a time zone string, extract a rule in the form
    773 ** date[/time]. See POSIX section 8 for the format of "date" and "time".
    774 ** If a valid rule is not found, return NULL.
    775 ** Otherwise, return a pointer to the first character not part of the rule.
    776 */
    777 
    778 static const char *
    779 getrule(strp, rulep)
    780 const char *			strp;
    781 register struct rule * const	rulep;
    782 {
    783 	if (*strp == 'J') {
    784 		/*
    785 		** Julian day.
    786 		*/
    787 		rulep->r_type = JULIAN_DAY;
    788 		++strp;
    789 		strp = getnum(strp, &rulep->r_day, 1, DAYSPERNYEAR);
    790 	} else if (*strp == 'M') {
    791 		/*
    792 		** Month, week, day.
    793 		*/
    794 		rulep->r_type = MONTH_NTH_DAY_OF_WEEK;
    795 		++strp;
    796 		strp = getnum(strp, &rulep->r_mon, 1, MONSPERYEAR);
    797 		if (strp == NULL)
    798 			return NULL;
    799 		if (*strp++ != '.')
    800 			return NULL;
    801 		strp = getnum(strp, &rulep->r_week, 1, 5);
    802 		if (strp == NULL)
    803 			return NULL;
    804 		if (*strp++ != '.')
    805 			return NULL;
    806 		strp = getnum(strp, &rulep->r_day, 0, DAYSPERWEEK - 1);
    807 	} else if (is_digit(*strp)) {
    808 		/*
    809 		** Day of year.
    810 		*/
    811 		rulep->r_type = DAY_OF_YEAR;
    812 		strp = getnum(strp, &rulep->r_day, 0, DAYSPERLYEAR - 1);
    813 	} else	return NULL;		/* invalid format */
    814 	if (strp == NULL)
    815 		return NULL;
    816 	if (*strp == '/') {
    817 		/*
    818 		** Time specified.
    819 		*/
    820 		++strp;
    821 		strp = getsecs(strp, &rulep->r_time);
    822 	} else	rulep->r_time = 2 * SECSPERHOUR;	/* default = 2:00:00 */
    823 	return strp;
    824 }
    825 
    826 /*
    827 ** Given the Epoch-relative time of January 1, 00:00:00 UTC, in a year, the
    828 ** year, a rule, and the offset from UTC at the time that rule takes effect,
    829 ** calculate the Epoch-relative time that rule takes effect.
    830 */
    831 
    832 static time_t
    833 transtime(janfirst, year, rulep, offset)
    834 const time_t				janfirst;
    835 const int				year;
    836 register const struct rule * const	rulep;
    837 const long				offset;
    838 {
    839 	register int	leapyear;
    840 	register time_t	value;
    841 	register int	i;
    842 	int		d, m1, yy0, yy1, yy2, dow;
    843 
    844 	INITIALIZE(value);
    845 	leapyear = isleap(year);
    846 	switch (rulep->r_type) {
    847 
    848 	case JULIAN_DAY:
    849 		/*
    850 		** Jn - Julian day, 1 == January 1, 60 == March 1 even in leap
    851 		** years.
    852 		** In non-leap years, or if the day number is 59 or less, just
    853 		** add SECSPERDAY times the day number-1 to the time of
    854 		** January 1, midnight, to get the day.
    855 		*/
    856 		value = janfirst + (rulep->r_day - 1) * SECSPERDAY;
    857 		if (leapyear && rulep->r_day >= 60)
    858 			value += SECSPERDAY;
    859 		break;
    860 
    861 	case DAY_OF_YEAR:
    862 		/*
    863 		** n - day of year.
    864 		** Just add SECSPERDAY times the day number to the time of
    865 		** January 1, midnight, to get the day.
    866 		*/
    867 		value = janfirst + rulep->r_day * SECSPERDAY;
    868 		break;
    869 
    870 	case MONTH_NTH_DAY_OF_WEEK:
    871 		/*
    872 		** Mm.n.d - nth "dth day" of month m.
    873 		*/
    874 		value = janfirst;
    875 		for (i = 0; i < rulep->r_mon - 1; ++i)
    876 			value += mon_lengths[leapyear][i] * SECSPERDAY;
    877 
    878 		/*
    879 		** Use Zeller's Congruence to get day-of-week of first day of
    880 		** month.
    881 		*/
    882 		m1 = (rulep->r_mon + 9) % 12 + 1;
    883 		yy0 = (rulep->r_mon <= 2) ? (year - 1) : year;
    884 		yy1 = yy0 / 100;
    885 		yy2 = yy0 % 100;
    886 		dow = ((26 * m1 - 2) / 10 +
    887 			1 + yy2 + yy2 / 4 + yy1 / 4 - 2 * yy1) % 7;
    888 		if (dow < 0)
    889 			dow += DAYSPERWEEK;
    890 
    891 		/*
    892 		** "dow" is the day-of-week of the first day of the month. Get
    893 		** the day-of-month (zero-origin) of the first "dow" day of the
    894 		** month.
    895 		*/
    896 		d = rulep->r_day - dow;
    897 		if (d < 0)
    898 			d += DAYSPERWEEK;
    899 		for (i = 1; i < rulep->r_week; ++i) {
    900 			if (d + DAYSPERWEEK >=
    901 				mon_lengths[leapyear][rulep->r_mon - 1])
    902 					break;
    903 			d += DAYSPERWEEK;
    904 		}
    905 
    906 		/*
    907 		** "d" is the day-of-month (zero-origin) of the day we want.
    908 		*/
    909 		value += d * SECSPERDAY;
    910 		break;
    911 	}
    912 
    913 	/*
    914 	** "value" is the Epoch-relative time of 00:00:00 UTC on the day in
    915 	** question. To get the Epoch-relative time of the specified local
    916 	** time on that day, add the transition time and the current offset
    917 	** from UTC.
    918 	*/
    919 	return value + rulep->r_time + offset;
    920 }
    921 
    922 /*
    923 ** Given a POSIX section 8-style TZ string, fill in the rule tables as
    924 ** appropriate.
    925 */
    926 
    927 static int
    928 tzparse(name, sp, lastditch)
    929 const char *			name;
    930 register struct state * const	sp;
    931 const int			lastditch;
    932 {
    933 	const char *			stdname;
    934 	const char *			dstname;
    935 	size_t				stdlen;
    936 	size_t				dstlen;
    937 	long				stdoffset;
    938 	long				dstoffset;
    939 	register time_t *		atp;
    940 	register unsigned char *	typep;
    941 	register char *			cp;
    942 	register int			load_result;
    943 
    944 	INITIALIZE(dstname);
    945 	stdname = name;
    946 	if (lastditch) {
    947 		stdlen = strlen(name);	/* length of standard zone name */
    948 		name += stdlen;
    949 		if (stdlen >= sizeof sp->chars)
    950 			stdlen = (sizeof sp->chars) - 1;
    951 		stdoffset = 0;
    952 	} else {
    953 		if (*name == '<') {
    954 			name++;
    955 			stdname = name;
    956 			name = getqzname(name, '>');
    957 			if (*name != '>')
    958 				return (-1);
    959 			stdlen = name - stdname;
    960 			name++;
    961 		} else {
    962 			name = getzname(name);
    963 			stdlen = name - stdname;
    964 		}
    965 		if (*name == '\0')
    966 			return -1;
    967 		name = getoffset(name, &stdoffset);
    968 		if (name == NULL)
    969 			return -1;
    970 	}
    971 	load_result = tzload(TZDEFRULES, sp, FALSE);
    972 	if (load_result != 0)
    973 		sp->leapcnt = 0;		/* so, we're off a little */
    974 	sp->timecnt = 0;
    975 	if (*name != '\0') {
    976 		if (*name == '<') {
    977 			dstname = ++name;
    978 			name = getqzname(name, '>');
    979 			if (*name != '>')
    980 				return -1;
    981 			dstlen = name - dstname;
    982 			name++;
    983 		} else {
    984 			dstname = name;
    985 			name = getzname(name);
    986 			dstlen = name - dstname; /* length of DST zone name */
    987 		}
    988 		if (*name != '\0' && *name != ',' && *name != ';') {
    989 			name = getoffset(name, &dstoffset);
    990 			if (name == NULL)
    991 				return -1;
    992 		} else	dstoffset = stdoffset - SECSPERHOUR;
    993 		if (*name == '\0' && load_result != 0)
    994 			name = TZDEFRULESTRING;
    995 		if (*name == ',' || *name == ';') {
    996 			struct rule	start;
    997 			struct rule	end;
    998 			register int	year;
    999 			register time_t	janfirst;
   1000 			time_t		starttime;
   1001 			time_t		endtime;
   1002 
   1003 			++name;
   1004 			if ((name = getrule(name, &start)) == NULL)
   1005 				return -1;
   1006 			if (*name++ != ',')
   1007 				return -1;
   1008 			if ((name = getrule(name, &end)) == NULL)
   1009 				return -1;
   1010 			if (*name != '\0')
   1011 				return -1;
   1012 			sp->typecnt = 2;	/* standard time and DST */
   1013 			/*
   1014 			** Two transitions per year, from EPOCH_YEAR forward.
   1015 			*/
   1016 			sp->ttis[0].tt_gmtoff = -dstoffset;
   1017 			sp->ttis[0].tt_isdst = 1;
   1018 			sp->ttis[0].tt_abbrind = stdlen + 1;
   1019 			sp->ttis[1].tt_gmtoff = -stdoffset;
   1020 			sp->ttis[1].tt_isdst = 0;
   1021 			sp->ttis[1].tt_abbrind = 0;
   1022 			atp = sp->ats;
   1023 			typep = sp->types;
   1024 			janfirst = 0;
   1025 			for (year = EPOCH_YEAR;
   1026 			    sp->timecnt + 2 <= TZ_MAX_TIMES;
   1027 			    ++year) {
   1028 			    	time_t	newfirst;
   1029 
   1030 				starttime = transtime(janfirst, year, &start,
   1031 					stdoffset);
   1032 				endtime = transtime(janfirst, year, &end,
   1033 					dstoffset);
   1034 				if (starttime > endtime) {
   1035 					*atp++ = endtime;
   1036 					*typep++ = 1;	/* DST ends */
   1037 					*atp++ = starttime;
   1038 					*typep++ = 0;	/* DST begins */
   1039 				} else {
   1040 					*atp++ = starttime;
   1041 					*typep++ = 0;	/* DST begins */
   1042 					*atp++ = endtime;
   1043 					*typep++ = 1;	/* DST ends */
   1044 				}
   1045 				sp->timecnt += 2;
   1046 				newfirst = janfirst;
   1047 				newfirst += year_lengths[isleap(year)] *
   1048 					SECSPERDAY;
   1049 				if (newfirst <= janfirst)
   1050 					break;
   1051 				janfirst = newfirst;
   1052 			}
   1053 		} else {
   1054 			register long	theirstdoffset;
   1055 			register long	theirdstoffset;
   1056 			register long	theiroffset;
   1057 			register int	isdst;
   1058 			register int	i;
   1059 			register int	j;
   1060 
   1061 			if (*name != '\0')
   1062 				return -1;
   1063 			/*
   1064 			** Initial values of theirstdoffset and theirdstoffset.
   1065 			*/
   1066 			theirstdoffset = 0;
   1067 			for (i = 0; i < sp->timecnt; ++i) {
   1068 				j = sp->types[i];
   1069 				if (!sp->ttis[j].tt_isdst) {
   1070 					theirstdoffset =
   1071 						-sp->ttis[j].tt_gmtoff;
   1072 					break;
   1073 				}
   1074 			}
   1075 			theirdstoffset = 0;
   1076 			for (i = 0; i < sp->timecnt; ++i) {
   1077 				j = sp->types[i];
   1078 				if (sp->ttis[j].tt_isdst) {
   1079 					theirdstoffset =
   1080 						-sp->ttis[j].tt_gmtoff;
   1081 					break;
   1082 				}
   1083 			}
   1084 			/*
   1085 			** Initially we're assumed to be in standard time.
   1086 			*/
   1087 			isdst = FALSE;
   1088 			theiroffset = theirstdoffset;
   1089 			/*
   1090 			** Now juggle transition times and types
   1091 			** tracking offsets as you do.
   1092 			*/
   1093 			for (i = 0; i < sp->timecnt; ++i) {
   1094 				j = sp->types[i];
   1095 				sp->types[i] = sp->ttis[j].tt_isdst;
   1096 				if (sp->ttis[j].tt_ttisgmt) {
   1097 					/* No adjustment to transition time */
   1098 				} else {
   1099 					/*
   1100 					** If summer time is in effect, and the
   1101 					** transition time was not specified as
   1102 					** standard time, add the summer time
   1103 					** offset to the transition time;
   1104 					** otherwise, add the standard time
   1105 					** offset to the transition time.
   1106 					*/
   1107 					/*
   1108 					** Transitions from DST to DDST
   1109 					** will effectively disappear since
   1110 					** POSIX provides for only one DST
   1111 					** offset.
   1112 					*/
   1113 					if (isdst && !sp->ttis[j].tt_ttisstd) {
   1114 						sp->ats[i] += dstoffset -
   1115 							theirdstoffset;
   1116 					} else {
   1117 						sp->ats[i] += stdoffset -
   1118 							theirstdoffset;
   1119 					}
   1120 				}
   1121 				theiroffset = -sp->ttis[j].tt_gmtoff;
   1122 				if (sp->ttis[j].tt_isdst)
   1123 					theirdstoffset = theiroffset;
   1124 				else	theirstdoffset = theiroffset;
   1125 			}
   1126 			/*
   1127 			** Finally, fill in ttis.
   1128 			** ttisstd and ttisgmt need not be handled.
   1129 			*/
   1130 			sp->ttis[0].tt_gmtoff = -stdoffset;
   1131 			sp->ttis[0].tt_isdst = FALSE;
   1132 			sp->ttis[0].tt_abbrind = 0;
   1133 			sp->ttis[1].tt_gmtoff = -dstoffset;
   1134 			sp->ttis[1].tt_isdst = TRUE;
   1135 			sp->ttis[1].tt_abbrind = stdlen + 1;
   1136 			sp->typecnt = 2;
   1137 		}
   1138 	} else {
   1139 		dstlen = 0;
   1140 		sp->typecnt = 1;		/* only standard time */
   1141 		sp->timecnt = 0;
   1142 		sp->ttis[0].tt_gmtoff = -stdoffset;
   1143 		sp->ttis[0].tt_isdst = 0;
   1144 		sp->ttis[0].tt_abbrind = 0;
   1145 	}
   1146 	sp->charcnt = stdlen + 1;
   1147 	if (dstlen != 0)
   1148 		sp->charcnt += dstlen + 1;
   1149 	if ((size_t) sp->charcnt > sizeof sp->chars)
   1150 		return -1;
   1151 	cp = sp->chars;
   1152 	(void) strncpy(cp, stdname, stdlen);
   1153 	cp += stdlen;
   1154 	*cp++ = '\0';
   1155 	if (dstlen != 0) {
   1156 		(void) strncpy(cp, dstname, dstlen);
   1157 		*(cp + dstlen) = '\0';
   1158 	}
   1159 	return 0;
   1160 }
   1161 
   1162 static void
   1163 gmtload(sp)
   1164 struct state * const	sp;
   1165 {
   1166 	if (tzload(gmt, sp, TRUE) != 0)
   1167 		(void) tzparse(gmt, sp, TRUE);
   1168 }
   1169 
   1170 /*
   1171 ** The easy way to behave "as if no library function calls" localtime
   1172 ** is to not call it--so we drop its guts into "localsub", which can be
   1173 ** freely called. (And no, the PANS doesn't require the above behavior--
   1174 ** but it *is* desirable.)
   1175 **
   1176 ** The unused offset argument is for the benefit of mktime variants.
   1177 */
   1178 
   1179 /*ARGSUSED*/
   1180 static struct tm *
   1181 localsub(timep, offset, tmp, sp)
   1182 const time_t * const	timep;
   1183 const long		offset;
   1184 struct tm * const	tmp;
   1185 const struct state *		sp;
   1186 {
   1187 	register const struct ttinfo *	ttisp;
   1188 	register int			i;
   1189 	register struct tm *		result;
   1190 	const time_t			t = *timep;
   1191 
   1192 #ifdef ALL_STATE
   1193 	if (sp == NULL)
   1194 		return gmtsub(timep, offset, tmp);
   1195 #endif /* defined ALL_STATE */
   1196 	if ((sp->goback && t < sp->ats[0]) ||
   1197 		(sp->goahead && t > sp->ats[sp->timecnt - 1])) {
   1198 			time_t			newt = t;
   1199 			register time_t		seconds;
   1200 			register time_t		tcycles;
   1201 			register int_fast64_t	icycles;
   1202 
   1203 			if (t < sp->ats[0])
   1204 				seconds = sp->ats[0] - t;
   1205 			else	seconds = t - sp->ats[sp->timecnt - 1];
   1206 			--seconds;
   1207 			tcycles = seconds / YEARSPERREPEAT / AVGSECSPERYEAR;
   1208 			++tcycles;
   1209 			icycles = tcycles;
   1210 			if (tcycles - icycles >= 1 || icycles - tcycles >= 1)
   1211 				return NULL;
   1212 			seconds = icycles;
   1213 			seconds *= YEARSPERREPEAT;
   1214 			seconds *= AVGSECSPERYEAR;
   1215 			if (t < sp->ats[0])
   1216 				newt += seconds;
   1217 			else	newt -= seconds;
   1218 			if (newt < sp->ats[0] ||
   1219 				newt > sp->ats[sp->timecnt - 1])
   1220 					return NULL;	/* "cannot happen" */
   1221 			result = localsub(&newt, offset, tmp, sp);
   1222 			if (result == tmp) {
   1223 				register time_t	newy;
   1224 
   1225 				newy = tmp->tm_year;
   1226 				if (t < sp->ats[0])
   1227 					newy -= icycles * YEARSPERREPEAT;
   1228 				else	newy += icycles * YEARSPERREPEAT;
   1229 				tmp->tm_year = newy;
   1230 				if (tmp->tm_year != newy)
   1231 					return NULL;
   1232 			}
   1233 			return result;
   1234 	}
   1235 	if (sp->timecnt == 0 || t < sp->ats[0]) {
   1236 		i = 0;
   1237 		while (sp->ttis[i].tt_isdst)
   1238 			if (++i >= sp->typecnt) {
   1239 				i = 0;
   1240 				break;
   1241 			}
   1242 	} else {
   1243 		register int	lo = 1;
   1244 		register int	hi = sp->timecnt;
   1245 
   1246 		while (lo < hi) {
   1247 			register int	mid = (lo + hi) >> 1;
   1248 
   1249 			if (t < sp->ats[mid])
   1250 				hi = mid;
   1251 			else	lo = mid + 1;
   1252 		}
   1253 		i = (int) sp->types[lo - 1];
   1254 	}
   1255 	ttisp = &sp->ttis[i];
   1256 	/*
   1257 	** To get (wrong) behavior that's compatible with System V Release 2.0
   1258 	** you'd replace the statement below with
   1259 	**	t += ttisp->tt_gmtoff;
   1260 	**	timesub(&t, 0L, sp, tmp);
   1261 	*/
   1262 	result = timesub(&t, ttisp->tt_gmtoff, sp, tmp);
   1263 	tmp->tm_isdst = ttisp->tt_isdst;
   1264 #ifdef HAVE_TM_GMTOFF
   1265 	tmp->tm_gmtoff = ttisp->tt_gmtoff;
   1266 #endif
   1267 	tzname[tmp->tm_isdst] = &sp->chars[ttisp->tt_abbrind];
   1268 #ifdef TM_ZONE
   1269 	tmp->TM_ZONE = &sp->chars[ttisp->tt_abbrind];
   1270 #endif /* defined TM_ZONE */
   1271 	return result;
   1272 }
   1273 
   1274 
   1275 // ============================================================================
   1276 #if 0
   1277 struct tm *
   1278 localtime(timep)
   1279 const time_t * const	timep;
   1280 {
   1281 	tzset();
   1282 	return localsub(timep, 0L, &tm);
   1283 }
   1284 #endif
   1285 
   1286 /*
   1287 ** Re-entrant version of localtime.
   1288 */
   1289 
   1290 // ============================================================================
   1291 void
   1292 localtime_tz(const time_t * const timep, struct tm * tmp, const char* tz)
   1293 {
   1294     struct state st;
   1295     if (tzload(tz, &st, TRUE) != 0) {
   1296         // not sure what's best here, but for now, we fall back to gmt
   1297         gmtload(&st);
   1298     }
   1299 
   1300 	localsub(timep, 0L, tmp, &st);
   1301 }
   1302 
   1303 /*
   1304 ** gmtsub is to gmtime as localsub is to localtime.
   1305 */
   1306 
   1307 static struct tm *
   1308 gmtsub(timep, offset, tmp)
   1309 const time_t * const	timep;
   1310 const long		offset;
   1311 struct tm * const	tmp;
   1312 {
   1313 	register struct tm *	result;
   1314 
   1315 	if (!gmt_is_set) {
   1316 		gmt_is_set = TRUE;
   1317 #ifdef ALL_STATE
   1318 		gmtptr = (struct state *) malloc(sizeof *gmtptr);
   1319 		if (gmtptr != NULL)
   1320 #endif /* defined ALL_STATE */
   1321 			gmtload(gmtptr);
   1322 	}
   1323 	result = timesub(timep, offset, gmtptr, tmp);
   1324 #ifdef TM_ZONE
   1325 	/*
   1326 	** Could get fancy here and deliver something such as
   1327 	** "UTC+xxxx" or "UTC-xxxx" if offset is non-zero,
   1328 	** but this is no time for a treasure hunt.
   1329 	*/
   1330 	if (offset != 0)
   1331 		tmp->TM_ZONE = wildabbr;
   1332 	else {
   1333 #ifdef ALL_STATE
   1334 		if (gmtptr == NULL)
   1335 			tmp->TM_ZONE = gmt;
   1336 		else	tmp->TM_ZONE = gmtptr->chars;
   1337 #endif /* defined ALL_STATE */
   1338 #ifndef ALL_STATE
   1339 		tmp->TM_ZONE = gmtptr->chars;
   1340 #endif /* State Farm */
   1341 	}
   1342 #endif /* defined TM_ZONE */
   1343 	return result;
   1344 }
   1345 
   1346 // ============================================================================
   1347 #if 0
   1348 struct tm *
   1349 gmtime(timep)
   1350 const time_t * const	timep;
   1351 {
   1352 	return gmtsub(timep, 0L, &tm);
   1353 }
   1354 #endif
   1355 
   1356 /*
   1357 * Re-entrant version of gmtime.
   1358 */
   1359 
   1360 // ============================================================================
   1361 #if 0
   1362 struct tm *
   1363 gmtime_r(timep, tmp)
   1364 const time_t * const	timep;
   1365 struct tm *		tmp;
   1366 {
   1367 	return gmtsub(timep, 0L, tmp);
   1368 }
   1369 #endif
   1370 
   1371 #ifdef STD_INSPIRED
   1372 
   1373 // ============================================================================
   1374 #if 0
   1375 struct tm *
   1376 offtime(timep, offset)
   1377 const time_t * const	timep;
   1378 const long		offset;
   1379 {
   1380 	return gmtsub(timep, offset, &tm);
   1381 }
   1382 #endif
   1383 
   1384 #endif /* defined STD_INSPIRED */
   1385 
   1386 /*
   1387 ** Return the number of leap years through the end of the given year
   1388 ** where, to make the math easy, the answer for year zero is defined as zero.
   1389 */
   1390 
   1391 static int
   1392 leaps_thru_end_of(y)
   1393 register const int	y;
   1394 {
   1395 	return (y >= 0) ? (y / 4 - y / 100 + y / 400) :
   1396 		-(leaps_thru_end_of(-(y + 1)) + 1);
   1397 }
   1398 
   1399 static struct tm *
   1400 timesub(timep, offset, sp, tmp)
   1401 const time_t * const			timep;
   1402 const long				offset;
   1403 register const struct state * const	sp;
   1404 register struct tm * const		tmp;
   1405 {
   1406 	register const struct lsinfo *	lp;
   1407 	register time_t			tdays;
   1408 	register int			idays;	/* unsigned would be so 2003 */
   1409 	register long			rem;
   1410 	int				y;
   1411 	register const int *		ip;
   1412 	register long			corr;
   1413 	register int			hit;
   1414 	register int			i;
   1415 
   1416 	corr = 0;
   1417 	hit = 0;
   1418 #ifdef ALL_STATE
   1419 	i = (sp == NULL) ? 0 : sp->leapcnt;
   1420 #endif /* defined ALL_STATE */
   1421 #ifndef ALL_STATE
   1422 	i = sp->leapcnt;
   1423 #endif /* State Farm */
   1424 	while (--i >= 0) {
   1425 		lp = &sp->lsis[i];
   1426 		if (*timep >= lp->ls_trans) {
   1427 			if (*timep == lp->ls_trans) {
   1428 				hit = ((i == 0 && lp->ls_corr > 0) ||
   1429 					lp->ls_corr > sp->lsis[i - 1].ls_corr);
   1430 				if (hit)
   1431 					while (i > 0 &&
   1432 						sp->lsis[i].ls_trans ==
   1433 						sp->lsis[i - 1].ls_trans + 1 &&
   1434 						sp->lsis[i].ls_corr ==
   1435 						sp->lsis[i - 1].ls_corr + 1) {
   1436 							++hit;
   1437 							--i;
   1438 					}
   1439 			}
   1440 			corr = lp->ls_corr;
   1441 			break;
   1442 		}
   1443 	}
   1444 	y = EPOCH_YEAR;
   1445 	tdays = *timep / SECSPERDAY;
   1446 	rem = *timep - tdays * SECSPERDAY;
   1447 	while (tdays < 0 || tdays >= year_lengths[isleap(y)]) {
   1448 		int		newy;
   1449 		register time_t	tdelta;
   1450 		register int	idelta;
   1451 		register int	leapdays;
   1452 
   1453 		tdelta = tdays / DAYSPERLYEAR;
   1454 		idelta = tdelta;
   1455 		if (tdelta - idelta >= 1 || idelta - tdelta >= 1)
   1456 			return NULL;
   1457 		if (idelta == 0)
   1458 			idelta = (tdays < 0) ? -1 : 1;
   1459 		newy = y;
   1460 		if (increment_overflow(&newy, idelta))
   1461 			return NULL;
   1462 		leapdays = leaps_thru_end_of(newy - 1) -
   1463 			leaps_thru_end_of(y - 1);
   1464 		tdays -= ((time_t) newy - y) * DAYSPERNYEAR;
   1465 		tdays -= leapdays;
   1466 		y = newy;
   1467 	}
   1468 	{
   1469 		register long	seconds;
   1470 
   1471 		seconds = tdays * SECSPERDAY + 0.5;
   1472 		tdays = seconds / SECSPERDAY;
   1473 		rem += seconds - tdays * SECSPERDAY;
   1474 	}
   1475 	/*
   1476 	** Given the range, we can now fearlessly cast...
   1477 	*/
   1478 	idays = tdays;
   1479 	rem += offset - corr;
   1480 	while (rem < 0) {
   1481 		rem += SECSPERDAY;
   1482 		--idays;
   1483 	}
   1484 	while (rem >= SECSPERDAY) {
   1485 		rem -= SECSPERDAY;
   1486 		++idays;
   1487 	}
   1488 	while (idays < 0) {
   1489 		if (increment_overflow(&y, -1))
   1490 			return NULL;
   1491 		idays += year_lengths[isleap(y)];
   1492 	}
   1493 	while (idays >= year_lengths[isleap(y)]) {
   1494 		idays -= year_lengths[isleap(y)];
   1495 		if (increment_overflow(&y, 1))
   1496 			return NULL;
   1497 	}
   1498 	tmp->tm_year = y;
   1499 	if (increment_overflow(&tmp->tm_year, -TM_YEAR_BASE))
   1500 		return NULL;
   1501 	tmp->tm_yday = idays;
   1502 	/*
   1503 	** The "extra" mods below avoid overflow problems.
   1504 	*/
   1505 	tmp->tm_wday = EPOCH_WDAY +
   1506 		((y - EPOCH_YEAR) % DAYSPERWEEK) *
   1507 		(DAYSPERNYEAR % DAYSPERWEEK) +
   1508 		leaps_thru_end_of(y - 1) -
   1509 		leaps_thru_end_of(EPOCH_YEAR - 1) +
   1510 		idays;
   1511 	tmp->tm_wday %= DAYSPERWEEK;
   1512 	if (tmp->tm_wday < 0)
   1513 		tmp->tm_wday += DAYSPERWEEK;
   1514 	tmp->tm_hour = (int) (rem / SECSPERHOUR);
   1515 	rem %= SECSPERHOUR;
   1516 	tmp->tm_min = (int) (rem / SECSPERMIN);
   1517 	/*
   1518 	** A positive leap second requires a special
   1519 	** representation. This uses "... ??:59:60" et seq.
   1520 	*/
   1521 	tmp->tm_sec = (int) (rem % SECSPERMIN) + hit;
   1522 	ip = mon_lengths[isleap(y)];
   1523 	for (tmp->tm_mon = 0; idays >= ip[tmp->tm_mon]; ++(tmp->tm_mon))
   1524 		idays -= ip[tmp->tm_mon];
   1525 	tmp->tm_mday = (int) (idays + 1);
   1526 	tmp->tm_isdst = 0;
   1527 #ifdef TM_GMTOFF
   1528 	tmp->TM_GMTOFF = offset;
   1529 #endif /* defined TM_GMTOFF */
   1530 	return tmp;
   1531 }
   1532 
   1533 // ============================================================================
   1534 #if 0
   1535 char *
   1536 ctime(timep)
   1537 const time_t * const	timep;
   1538 {
   1539 /*
   1540 ** Section 4.12.3.2 of X3.159-1989 requires that
   1541 **	The ctime function converts the calendar time pointed to by timer
   1542 **	to local time in the form of a string. It is equivalent to
   1543 **		asctime(localtime(timer))
   1544 */
   1545 	return asctime(localtime(timep));
   1546 }
   1547 #endif
   1548 
   1549 // ============================================================================
   1550 #if 0
   1551 char *
   1552 ctime_r(timep, buf)
   1553 const time_t * const	timep;
   1554 char *			buf;
   1555 {
   1556 	struct tm	mytm;
   1557 
   1558 	return asctime_r(localtime_r(timep, &mytm), buf);
   1559 }
   1560 #endif
   1561 
   1562 /*
   1563 ** Adapted from code provided by Robert Elz, who writes:
   1564 **	The "best" way to do mktime I think is based on an idea of Bob
   1565 **	Kridle's (so its said...) from a long time ago.
   1566 **	It does a binary search of the time_t space. Since time_t's are
   1567 **	just 32 bits, its a max of 32 iterations (even at 64 bits it
   1568 **	would still be very reasonable).
   1569 */
   1570 
   1571 #ifndef WRONG
   1572 #define WRONG	(-1)
   1573 #endif /* !defined WRONG */
   1574 
   1575 /*
   1576 ** Simplified normalize logic courtesy Paul Eggert.
   1577 */
   1578 
   1579 static int
   1580 increment_overflow(number, delta)
   1581 int *   number;
   1582 int delta;
   1583 {
   1584     unsigned  number0 = (unsigned)*number;
   1585     unsigned  number1 = (unsigned)(number0 + delta);
   1586 
   1587     *number = (int)number1;
   1588 
   1589     if (delta >= 0) {
   1590         return ((int)number1 < (int)number0);
   1591     } else {
   1592         return ((int)number1 > (int)number0);
   1593     }
   1594 }
   1595 
   1596 static int
   1597 long_increment_overflow(number, delta)
   1598 long *  number;
   1599 int delta;
   1600 {
   1601     unsigned long  number0 = (unsigned long)*number;
   1602     unsigned long  number1 = (unsigned long)(number0 + delta);
   1603 
   1604     *number = (long)number1;
   1605 
   1606     if (delta >= 0) {
   1607         return ((long)number1 < (long)number0);
   1608     } else {
   1609         return ((long)number1 > (long)number0);
   1610     }
   1611 }
   1612 
   1613 static int
   1614 normalize_overflow(tensptr, unitsptr, base)
   1615 int * const	tensptr;
   1616 int * const	unitsptr;
   1617 const int	base;
   1618 {
   1619 	register int	tensdelta;
   1620 
   1621 	tensdelta = (*unitsptr >= 0) ?
   1622 		(*unitsptr / base) :
   1623 		(-1 - (-1 - *unitsptr) / base);
   1624 	*unitsptr -= tensdelta * base;
   1625 	return increment_overflow(tensptr, tensdelta);
   1626 }
   1627 
   1628 static int
   1629 long_normalize_overflow(tensptr, unitsptr, base)
   1630 long * const	tensptr;
   1631 int * const	unitsptr;
   1632 const int	base;
   1633 {
   1634 	register int	tensdelta;
   1635 
   1636 	tensdelta = (*unitsptr >= 0) ?
   1637 		(*unitsptr / base) :
   1638 		(-1 - (-1 - *unitsptr) / base);
   1639 	*unitsptr -= tensdelta * base;
   1640 	return long_increment_overflow(tensptr, tensdelta);
   1641 }
   1642 
   1643 static int
   1644 tmcomp(atmp, btmp)
   1645 register const struct tm * const atmp;
   1646 register const struct tm * const btmp;
   1647 {
   1648 	register int	result;
   1649 
   1650 	if ((result = (atmp->tm_year - btmp->tm_year)) == 0 &&
   1651 		(result = (atmp->tm_mon - btmp->tm_mon)) == 0 &&
   1652 		(result = (atmp->tm_mday - btmp->tm_mday)) == 0 &&
   1653 		(result = (atmp->tm_hour - btmp->tm_hour)) == 0 &&
   1654 		(result = (atmp->tm_min - btmp->tm_min)) == 0)
   1655 			result = atmp->tm_sec - btmp->tm_sec;
   1656 	return result;
   1657 }
   1658 
   1659 static time_t
   1660 time2sub(tmp, funcp, offset, okayp, do_norm_secs, sp)
   1661 struct tm * const	tmp;
   1662 struct tm * (* const	funcp) P((const time_t*, long, struct tm*,const struct state *sp));
   1663 const long		offset;
   1664 int * const		okayp;
   1665 const int		do_norm_secs;
   1666 const struct state *	sp;
   1667 {
   1668 	register int			dir;
   1669 	register int			i, j;
   1670 	register int			saved_seconds;
   1671 	register long			li;
   1672 	register time_t			lo;
   1673 	register time_t			hi;
   1674 	long				y;
   1675 	time_t				newt;
   1676 	time_t				t;
   1677 	struct tm			yourtm, mytm;
   1678 
   1679 	*okayp = FALSE;
   1680 	yourtm = *tmp;
   1681 	if (do_norm_secs) {
   1682 		if (normalize_overflow(&yourtm.tm_min, &yourtm.tm_sec,
   1683 			SECSPERMIN))
   1684 				return WRONG;
   1685 	}
   1686 	if (normalize_overflow(&yourtm.tm_hour, &yourtm.tm_min, MINSPERHOUR))
   1687 		return WRONG;
   1688 	if (normalize_overflow(&yourtm.tm_mday, &yourtm.tm_hour, HOURSPERDAY))
   1689 		return WRONG;
   1690 	y = yourtm.tm_year;
   1691 	if (long_normalize_overflow(&y, &yourtm.tm_mon, MONSPERYEAR))
   1692 		return WRONG;
   1693 	/*
   1694 	** Turn y into an actual year number for now.
   1695 	** It is converted back to an offset from TM_YEAR_BASE later.
   1696 	*/
   1697 	if (long_increment_overflow(&y, TM_YEAR_BASE))
   1698 		return WRONG;
   1699 	while (yourtm.tm_mday <= 0) {
   1700 		if (long_increment_overflow(&y, -1))
   1701 			return WRONG;
   1702 		li = y + (1 < yourtm.tm_mon);
   1703 		yourtm.tm_mday += year_lengths[isleap(li)];
   1704 	}
   1705 	while (yourtm.tm_mday > DAYSPERLYEAR) {
   1706 		li = y + (1 < yourtm.tm_mon);
   1707 		yourtm.tm_mday -= year_lengths[isleap(li)];
   1708 		if (long_increment_overflow(&y, 1))
   1709 			return WRONG;
   1710 	}
   1711 	for ( ; ; ) {
   1712 		i = mon_lengths[isleap(y)][yourtm.tm_mon];
   1713 		if (yourtm.tm_mday <= i)
   1714 			break;
   1715 		yourtm.tm_mday -= i;
   1716 		if (++yourtm.tm_mon >= MONSPERYEAR) {
   1717 			yourtm.tm_mon = 0;
   1718 			if (long_increment_overflow(&y, 1))
   1719 				return WRONG;
   1720 		}
   1721 	}
   1722 	if (long_increment_overflow(&y, -TM_YEAR_BASE))
   1723 		return WRONG;
   1724 	yourtm.tm_year = y;
   1725 	if (yourtm.tm_year != y)
   1726 		return WRONG;
   1727 	if (yourtm.tm_sec >= 0 && yourtm.tm_sec < SECSPERMIN)
   1728 		saved_seconds = 0;
   1729 	else if (y + TM_YEAR_BASE < EPOCH_YEAR) {
   1730 		/*
   1731 		** We can't set tm_sec to 0, because that might push the
   1732 		** time below the minimum representable time.
   1733 		** Set tm_sec to 59 instead.
   1734 		** This assumes that the minimum representable time is
   1735 		** not in the same minute that a leap second was deleted from,
   1736 		** which is a safer assumption than using 58 would be.
   1737 		*/
   1738 		if (increment_overflow(&yourtm.tm_sec, 1 - SECSPERMIN))
   1739 			return WRONG;
   1740 		saved_seconds = yourtm.tm_sec;
   1741 		yourtm.tm_sec = SECSPERMIN - 1;
   1742 	} else {
   1743 		saved_seconds = yourtm.tm_sec;
   1744 		yourtm.tm_sec = 0;
   1745 	}
   1746 	/*
   1747 	** Do a binary search (this works whatever time_t's type is).
   1748 	*/
   1749 	if (!TYPE_SIGNED(time_t)) {
   1750 		lo = 0;
   1751 		hi = lo - 1;
   1752 	} else if (!TYPE_INTEGRAL(time_t)) {
   1753 		if (sizeof(time_t) > sizeof(float))
   1754 			hi = (time_t) DBL_MAX;
   1755 		else	hi = (time_t) FLT_MAX;
   1756 		lo = -hi;
   1757 	} else {
   1758 		lo = 1;
   1759 		for (i = 0; i < (int) TYPE_BIT(time_t) - 1; ++i)
   1760 			lo *= 2;
   1761 		hi = -(lo + 1);
   1762 	}
   1763 	for ( ; ; ) {
   1764 		t = lo / 2 + hi / 2;
   1765 		if (t < lo)
   1766 			t = lo;
   1767 		else if (t > hi)
   1768 			t = hi;
   1769 		if ((*funcp)(&t, offset, &mytm, sp) == NULL) {
   1770 			/*
   1771 			** Assume that t is too extreme to be represented in
   1772 			** a struct tm; arrange things so that it is less
   1773 			** extreme on the next pass.
   1774 			*/
   1775 			dir = (t > 0) ? 1 : -1;
   1776 		} else	dir = tmcomp(&mytm, &yourtm);
   1777 		if (dir != 0) {
   1778 			if (t == lo) {
   1779 			        if (t == TIME_T_MAX)
   1780 			             return WRONG;
   1781 				++t;
   1782 				++lo;
   1783 			} else if (t == hi) {
   1784 			        if (t == TIME_T_MIN)
   1785 			             return WRONG;
   1786 				--t;
   1787 				--hi;
   1788 			}
   1789 			if (lo > hi)
   1790 				return WRONG;
   1791 			if (dir > 0)
   1792 				hi = t;
   1793 			else	lo = t;
   1794 			continue;
   1795 		}
   1796 		if (yourtm.tm_isdst < 0 || mytm.tm_isdst == yourtm.tm_isdst)
   1797 			break;
   1798 		/*
   1799 		** Right time, wrong type.
   1800 		** Hunt for right time, right type.
   1801 		** It's okay to guess wrong since the guess
   1802 		** gets checked.
   1803 		*/
   1804 		/*
   1805 		** The (void *) casts are the benefit of SunOS 3.3 on Sun 2's.
   1806 		*/
   1807 #ifdef ALL_STATE
   1808 		if (sp == NULL)
   1809 			return WRONG;
   1810 #endif /* defined ALL_STATE */
   1811 		for (i = sp->typecnt - 1; i >= 0; --i) {
   1812 			if (sp->ttis[i].tt_isdst != yourtm.tm_isdst)
   1813 				continue;
   1814 			for (j = sp->typecnt - 1; j >= 0; --j) {
   1815 				if (sp->ttis[j].tt_isdst == yourtm.tm_isdst)
   1816 					continue;
   1817 				newt = t + sp->ttis[j].tt_gmtoff -
   1818 					sp->ttis[i].tt_gmtoff;
   1819 				if ((*funcp)(&newt, offset, &mytm, sp) == NULL)
   1820 					continue;
   1821 				if (tmcomp(&mytm, &yourtm) != 0)
   1822 					continue;
   1823 				if (mytm.tm_isdst != yourtm.tm_isdst)
   1824 					continue;
   1825 				/*
   1826 				** We have a match.
   1827 				*/
   1828 				t = newt;
   1829 				goto label;
   1830 			}
   1831 		}
   1832 		return WRONG;
   1833 	}
   1834 label:
   1835 	newt = t + saved_seconds;
   1836 	if ((newt < t) != (saved_seconds < 0))
   1837 		return WRONG;
   1838 	t = newt;
   1839 	if ((*funcp)(&t, offset, tmp, sp))
   1840 		*okayp = TRUE;
   1841 	return t;
   1842 }
   1843 
   1844 static time_t
   1845 time2(tmp, funcp, offset, okayp, sp)
   1846 struct tm * const	tmp;
   1847 struct tm * (* const	funcp) P((const time_t*, long, struct tm*,
   1848             const struct state* sp));
   1849 const long		offset;
   1850 int * const		okayp;
   1851 const struct state *	sp;
   1852 {
   1853 	time_t	t;
   1854 
   1855 	/*
   1856 	** First try without normalization of seconds
   1857 	** (in case tm_sec contains a value associated with a leap second).
   1858 	** If that fails, try with normalization of seconds.
   1859 	*/
   1860 	t = time2sub(tmp, funcp, offset, okayp, FALSE, sp);
   1861 	return *okayp ? t : time2sub(tmp, funcp, offset, okayp, TRUE, sp);
   1862 }
   1863 
   1864 static time_t
   1865 time1(tmp, funcp, offset, sp)
   1866 struct tm * const	tmp;
   1867 struct tm * (* const	funcp) P((const time_t *, long, struct tm *, const struct state* sp));
   1868 const long		offset;
   1869 const struct state *	sp;
   1870 {
   1871 	register time_t			t;
   1872 	register int			samei, otheri;
   1873 	register int			sameind, otherind;
   1874 	register int			i;
   1875 	register int			nseen;
   1876 	int				seen[TZ_MAX_TYPES];
   1877 	int				types[TZ_MAX_TYPES];
   1878 	int				okay;
   1879 
   1880 	if (tmp->tm_isdst > 1)
   1881 		tmp->tm_isdst = 1;
   1882 	t = time2(tmp, funcp, offset, &okay, sp);
   1883 #define PCTS 1
   1884 #ifdef PCTS
   1885 	/*
   1886 	** PCTS code courtesy Grant Sullivan.
   1887 	*/
   1888 	if (okay)
   1889 		return t;
   1890 	if (tmp->tm_isdst < 0)
   1891 		tmp->tm_isdst = 0;	/* reset to std and try again */
   1892 #endif /* defined PCTS */
   1893 #ifndef PCTS
   1894 	if (okay || tmp->tm_isdst < 0)
   1895 		return t;
   1896 #endif /* !defined PCTS */
   1897 	/*
   1898 	** We're supposed to assume that somebody took a time of one type
   1899 	** and did some math on it that yielded a "struct tm" that's bad.
   1900 	** We try to divine the type they started from and adjust to the
   1901 	** type they need.
   1902 	*/
   1903 	/*
   1904 	** The (void *) casts are the benefit of SunOS 3.3 on Sun 2's.
   1905 	*/
   1906 #ifdef ALL_STATE
   1907 	if (sp == NULL)
   1908 		return WRONG;
   1909 #endif /* defined ALL_STATE */
   1910 	for (i = 0; i < sp->typecnt; ++i)
   1911 		seen[i] = FALSE;
   1912 	nseen = 0;
   1913 	for (i = sp->timecnt - 1; i >= 0; --i)
   1914 		if (!seen[sp->types[i]]) {
   1915 			seen[sp->types[i]] = TRUE;
   1916 			types[nseen++] = sp->types[i];
   1917 		}
   1918 	for (sameind = 0; sameind < nseen; ++sameind) {
   1919 		samei = types[sameind];
   1920 		if (sp->ttis[samei].tt_isdst != tmp->tm_isdst)
   1921 			continue;
   1922 		for (otherind = 0; otherind < nseen; ++otherind) {
   1923 			otheri = types[otherind];
   1924 			if (sp->ttis[otheri].tt_isdst == tmp->tm_isdst)
   1925 				continue;
   1926 			tmp->tm_sec += sp->ttis[otheri].tt_gmtoff -
   1927 					sp->ttis[samei].tt_gmtoff;
   1928 			tmp->tm_isdst = !tmp->tm_isdst;
   1929 			t = time2(tmp, funcp, offset, &okay, sp);
   1930 			if (okay)
   1931 				return t;
   1932 			tmp->tm_sec -= sp->ttis[otheri].tt_gmtoff -
   1933 					sp->ttis[samei].tt_gmtoff;
   1934 			tmp->tm_isdst = !tmp->tm_isdst;
   1935 		}
   1936 	}
   1937 	return WRONG;
   1938 }
   1939 
   1940 // ============================================================================
   1941 time_t
   1942 mktime_tz(struct tm * const	tmp, char const * tz)
   1943 {
   1944     struct state st;
   1945     if (tzload(tz, &st, TRUE) != 0) {
   1946         // not sure what's best here, but for now, we fall back to gmt
   1947         gmtload(&st);
   1948     }
   1949 	return time1(tmp, localsub, 0L, &st);
   1950 }
   1951