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