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
1290