Deleted Added
full compact
localtime.c (8870) localtime.c (9936)
1#ifndef lint
2#ifndef NOID
1#ifndef lint
2#ifndef NOID
3static char elsieid[] = "@(#)localtime.c 7.19";
3static char elsieid[] = "@(#)localtime.c 7.44";
4#endif /* !defined NOID */
5#endif /* !defined lint */
6
7/*
8** Leap second handling from Bradley White (bww@k.gp.cs.cmu.edu).
9** POSIX-style TZ environment variable handling from Guy Harris
10** (guy@auspex.com).
11*/
12
13/*LINTLIBRARY*/
14
15#include "private.h"
16#include "tzfile.h"
17#include "fcntl.h"
18
4#endif /* !defined NOID */
5#endif /* !defined lint */
6
7/*
8** Leap second handling from Bradley White (bww@k.gp.cs.cmu.edu).
9** POSIX-style TZ environment variable handling from Guy Harris
10** (guy@auspex.com).
11*/
12
13/*LINTLIBRARY*/
14
15#include "private.h"
16#include "tzfile.h"
17#include "fcntl.h"
18
19#define ACCESS_MODE O_RDONLY
19/*
20** SunOS 4.1.1 headers lack O_BINARY.
21*/
20
21#ifdef O_BINARY
22#define OPEN_MODE (O_RDONLY | O_BINARY)
23#endif /* defined O_BINARY */
24#ifndef O_BINARY
25#define OPEN_MODE O_RDONLY
26#endif /* !defined O_BINARY */
27
28#ifndef WILDABBR
29/*
30** Someone might make incorrect use of a time zone abbreviation:
31** 1. They might reference tzname[0] before calling tzset (explicitly
22
23#ifdef O_BINARY
24#define OPEN_MODE (O_RDONLY | O_BINARY)
25#endif /* defined O_BINARY */
26#ifndef O_BINARY
27#define OPEN_MODE O_RDONLY
28#endif /* !defined O_BINARY */
29
30#ifndef WILDABBR
31/*
32** Someone might make incorrect use of a time zone abbreviation:
33** 1. They might reference tzname[0] before calling tzset (explicitly
32** or implicitly).
34** or implicitly).
33** 2. They might reference tzname[1] before calling tzset (explicitly
35** 2. They might reference tzname[1] before calling tzset (explicitly
34** or implicitly).
36** or implicitly).
35** 3. They might reference tzname[1] after setting to a time zone
36** in which Daylight Saving Time is never observed.
37** 4. They might reference tzname[0] after setting to a time zone
38** in which Standard Time is never observed.
39** 5. They might reference tm.TM_ZONE after calling offtime.
40** What's best to do in the above cases is open to debate;
41** for now, we just set things up so that in any of the five cases
42** WILDABBR is used. Another possibility: initialize tzname[0] to the
43** string "tzname[0] used before set", and similarly for the other cases.
44** And another: initialize tzname[0] to "ERA", with an explanation in the
45** manual page of what this "time zone abbreviation" means (doing this so
46** that tzname[0] has the "normal" length of three characters).
47*/
48#define WILDABBR " "
49#endif /* !defined WILDABBR */
50
37** 3. They might reference tzname[1] after setting to a time zone
38** in which Daylight Saving Time is never observed.
39** 4. They might reference tzname[0] after setting to a time zone
40** in which Standard Time is never observed.
41** 5. They might reference tm.TM_ZONE after calling offtime.
42** What's best to do in the above cases is open to debate;
43** for now, we just set things up so that in any of the five cases
44** WILDABBR is used. Another possibility: initialize tzname[0] to the
45** string "tzname[0] used before set", and similarly for the other cases.
46** And another: initialize tzname[0] to "ERA", with an explanation in the
47** manual page of what this "time zone abbreviation" means (doing this so
48** that tzname[0] has the "normal" length of three characters).
49*/
50#define WILDABBR " "
51#endif /* !defined WILDABBR */
52
51static const char GMT[] = "GMT";
53static char wildabbr[] = "WILDABBR";
52
54
55static const char gmt[] = "GMT";
56
53struct ttinfo { /* time type information */
54 long tt_gmtoff; /* GMT offset in seconds */
55 int tt_isdst; /* used to set tm_isdst */
56 int tt_abbrind; /* abbreviation list index */
57 int tt_ttisstd; /* TRUE if transition is std time */
57struct ttinfo { /* time type information */
58 long tt_gmtoff; /* GMT offset in seconds */
59 int tt_isdst; /* used to set tm_isdst */
60 int tt_abbrind; /* abbreviation list index */
61 int tt_ttisstd; /* TRUE if transition is std time */
62 int tt_ttisgmt; /* TRUE if transition is GMT */
58};
59
60struct lsinfo { /* leap second information */
61 time_t ls_trans; /* transition time */
62 long ls_corr; /* correction to apply */
63};
64
65#define BIGGEST(a, b) (((a) > (b)) ? (a) : (b))
66
67#ifdef TZNAME_MAX
68#define MY_TZNAME_MAX TZNAME_MAX
69#endif /* defined TZNAME_MAX */
70#ifndef TZNAME_MAX
71#define MY_TZNAME_MAX 255
72#endif /* !defined TZNAME_MAX */
73
74struct state {
75 int leapcnt;
76 int timecnt;
77 int typecnt;
78 int charcnt;
79 time_t ats[TZ_MAX_TIMES];
80 unsigned char types[TZ_MAX_TIMES];
81 struct ttinfo ttis[TZ_MAX_TYPES];
63};
64
65struct lsinfo { /* leap second information */
66 time_t ls_trans; /* transition time */
67 long ls_corr; /* correction to apply */
68};
69
70#define BIGGEST(a, b) (((a) > (b)) ? (a) : (b))
71
72#ifdef TZNAME_MAX
73#define MY_TZNAME_MAX TZNAME_MAX
74#endif /* defined TZNAME_MAX */
75#ifndef TZNAME_MAX
76#define MY_TZNAME_MAX 255
77#endif /* !defined TZNAME_MAX */
78
79struct state {
80 int leapcnt;
81 int timecnt;
82 int typecnt;
83 int charcnt;
84 time_t ats[TZ_MAX_TIMES];
85 unsigned char types[TZ_MAX_TIMES];
86 struct ttinfo ttis[TZ_MAX_TYPES];
82 char chars[BIGGEST(BIGGEST(TZ_MAX_CHARS + 1, sizeof GMT),
87 char chars[BIGGEST(BIGGEST(TZ_MAX_CHARS + 1, sizeof gmt),
83 (2 * (MY_TZNAME_MAX + 1)))];
84 struct lsinfo lsis[TZ_MAX_LEAPS];
85};
86
87struct rule {
88 int r_type; /* type of rule--see below */
89 int r_day; /* day number of rule */
90 int r_week; /* week number of rule */
91 int r_mon; /* month number of rule */
92 long r_time; /* transition time of rule */
93};
94
95#define JULIAN_DAY 0 /* Jn - Julian day */
96#define DAY_OF_YEAR 1 /* n - day of year */
97#define MONTH_NTH_DAY_OF_WEEK 2 /* Mm.n.d - month, week, day of week */
98
99/*
100** Prototypes for static functions.
101*/
102
103static long detzcode P((const char * codep));
104static const char * getzname P((const char * strp));
105static const char * getnum P((const char * strp, int * nump, int min,
106 int max));
107static const char * getsecs P((const char * strp, long * secsp));
108static const char * getoffset P((const char * strp, long * offsetp));
109static const char * getrule P((const char * strp, struct rule * rulep));
110static void gmtload P((struct state * sp));
111static void gmtsub P((const time_t * timep, long offset,
112 struct tm * tmp));
113static void localsub P((const time_t * timep, long offset,
114 struct tm * tmp));
115static int increment_overflow P((int * number, int delta));
116static int normalize_overflow P((int * tensptr, int * unitsptr,
117 int base));
118static void settzname P((void));
88 (2 * (MY_TZNAME_MAX + 1)))];
89 struct lsinfo lsis[TZ_MAX_LEAPS];
90};
91
92struct rule {
93 int r_type; /* type of rule--see below */
94 int r_day; /* day number of rule */
95 int r_week; /* week number of rule */
96 int r_mon; /* month number of rule */
97 long r_time; /* transition time of rule */
98};
99
100#define JULIAN_DAY 0 /* Jn - Julian day */
101#define DAY_OF_YEAR 1 /* n - day of year */
102#define MONTH_NTH_DAY_OF_WEEK 2 /* Mm.n.d - month, week, day of week */
103
104/*
105** Prototypes for static functions.
106*/
107
108static long detzcode P((const char * codep));
109static const char * getzname P((const char * strp));
110static const char * getnum P((const char * strp, int * nump, int min,
111 int max));
112static const char * getsecs P((const char * strp, long * secsp));
113static const char * getoffset P((const char * strp, long * offsetp));
114static const char * getrule P((const char * strp, struct rule * rulep));
115static void gmtload P((struct state * sp));
116static void gmtsub P((const time_t * timep, long offset,
117 struct tm * tmp));
118static void localsub P((const time_t * timep, long offset,
119 struct tm * tmp));
120static int increment_overflow P((int * number, int delta));
121static int normalize_overflow P((int * tensptr, int * unitsptr,
122 int base));
123static void settzname P((void));
119static time_t time1 P((struct tm * tmp, void (* funcp)(),
124static time_t time1 P((struct tm * tmp,
125 void(*funcp) P((const time_t *,
126 long, struct tm *)),
120 long offset));
127 long offset));
121static time_t time2 P((struct tm *tmp, void (* funcp)(),
128static time_t time2 P((struct tm *tmp,
129 void(*funcp) P((const time_t *,
130 long, struct tm*)),
122 long offset, int * okayp));
123static void timesub P((const time_t * timep, long offset,
124 const struct state * sp, struct tm * tmp));
125static int tmcomp P((const struct tm * atmp,
126 const struct tm * btmp));
127static time_t transtime P((time_t janfirst, int year,
128 const struct rule * rulep, long offset));
129static int tzload P((const char * name, struct state * sp));
130static int tzparse P((const char * name, struct state * sp,
131 int lastditch));
132
133#ifdef ALL_STATE
134static struct state * lclptr;
135static struct state * gmtptr;
136#endif /* defined ALL_STATE */
137
138#ifndef ALL_STATE
139static struct state lclmem;
140static struct state gmtmem;
141#define lclptr (&lclmem)
142#define gmtptr (&gmtmem)
143#endif /* State Farm */
144
131 long offset, int * okayp));
132static void timesub P((const time_t * timep, long offset,
133 const struct state * sp, struct tm * tmp));
134static int tmcomp P((const struct tm * atmp,
135 const struct tm * btmp));
136static time_t transtime P((time_t janfirst, int year,
137 const struct rule * rulep, long offset));
138static int tzload P((const char * name, struct state * sp));
139static int tzparse P((const char * name, struct state * sp,
140 int lastditch));
141
142#ifdef ALL_STATE
143static struct state * lclptr;
144static struct state * gmtptr;
145#endif /* defined ALL_STATE */
146
147#ifndef ALL_STATE
148static struct state lclmem;
149static struct state gmtmem;
150#define lclptr (&lclmem)
151#define gmtptr (&gmtmem)
152#endif /* State Farm */
153
154#ifndef TZ_STRLEN_MAX
155#define TZ_STRLEN_MAX 255
156#endif /* !defined TZ_STRLEN_MAX */
157
158static char lcl_TZname[TZ_STRLEN_MAX + 1];
145static int lcl_is_set;
146static int gmt_is_set;
147
148char * tzname[2] = {
159static int lcl_is_set;
160static int gmt_is_set;
161
162char * tzname[2] = {
149 WILDABBR,
150 WILDABBR
163 wildabbr,
164 wildabbr
151};
152
165};
166
167/*
168** Section 4.12.3 of X3.159-1989 requires that
169** Except for the strftime function, these functions [asctime,
170** ctime, gmtime, localtime] return values in one of two static
171** objects: a broken-down time structure and an array of char.
172** Thanks to Paul Eggert (eggert@twinsun.com) for noting this.
173*/
174
175static struct tm tm;
176
153#ifdef USG_COMPAT
154time_t timezone = 0;
155int daylight = 0;
156#endif /* defined USG_COMPAT */
157
158#ifdef ALTZONE
159time_t altzone = 0;
160#endif /* defined ALTZONE */
161
162static long
163detzcode(codep)
164const char * const codep;
165{
166 register long result;
167 register int i;
168
177#ifdef USG_COMPAT
178time_t timezone = 0;
179int daylight = 0;
180#endif /* defined USG_COMPAT */
181
182#ifdef ALTZONE
183time_t altzone = 0;
184#endif /* defined ALTZONE */
185
186static long
187detzcode(codep)
188const char * const codep;
189{
190 register long result;
191 register int i;
192
169 result = 0;
193 result = (codep[0] & 0x80) ? ~0L : 0L;
170 for (i = 0; i < 4; ++i)
171 result = (result << 8) | (codep[i] & 0xff);
172 return result;
173}
174
175static void
194 for (i = 0; i < 4; ++i)
195 result = (result << 8) | (codep[i] & 0xff);
196 return result;
197}
198
199static void
176settzname()
200settzname P((void))
177{
201{
178 register const struct state * const sp = lclptr;
202 register struct state * const sp = lclptr;
179 register int i;
180
203 register int i;
204
181 tzname[0] = WILDABBR;
182 tzname[1] = WILDABBR;
205 tzname[0] = wildabbr;
206 tzname[1] = wildabbr;
183#ifdef USG_COMPAT
184 daylight = 0;
185 timezone = 0;
186#endif /* defined USG_COMPAT */
187#ifdef ALTZONE
188 altzone = 0;
189#endif /* defined ALTZONE */
190#ifdef ALL_STATE
191 if (sp == NULL) {
207#ifdef USG_COMPAT
208 daylight = 0;
209 timezone = 0;
210#endif /* defined USG_COMPAT */
211#ifdef ALTZONE
212 altzone = 0;
213#endif /* defined ALTZONE */
214#ifdef ALL_STATE
215 if (sp == NULL) {
192 tzname[0] = tzname[1] = GMT;
216 tzname[0] = tzname[1] = gmt;
193 return;
194 }
195#endif /* defined ALL_STATE */
196 for (i = 0; i < sp->typecnt; ++i) {
197 register const struct ttinfo * const ttisp = &sp->ttis[i];
198
199 tzname[ttisp->tt_isdst] =
217 return;
218 }
219#endif /* defined ALL_STATE */
220 for (i = 0; i < sp->typecnt; ++i) {
221 register const struct ttinfo * const ttisp = &sp->ttis[i];
222
223 tzname[ttisp->tt_isdst] =
200 (char *) &sp->chars[ttisp->tt_abbrind];
224 &sp->chars[ttisp->tt_abbrind];
201#ifdef USG_COMPAT
202 if (ttisp->tt_isdst)
203 daylight = 1;
204 if (i == 0 || !ttisp->tt_isdst)
205 timezone = -(ttisp->tt_gmtoff);
206#endif /* defined USG_COMPAT */
207#ifdef ALTZONE
208 if (i == 0 || ttisp->tt_isdst)
209 altzone = -(ttisp->tt_gmtoff);
210#endif /* defined ALTZONE */
211 }
212 /*
213 ** And to get the latest zone names into tzname. . .
214 */
215 for (i = 0; i < sp->timecnt; ++i) {
216 register const struct ttinfo * const ttisp =
217 &sp->ttis[
218 sp->types[i]];
219
220 tzname[ttisp->tt_isdst] =
225#ifdef USG_COMPAT
226 if (ttisp->tt_isdst)
227 daylight = 1;
228 if (i == 0 || !ttisp->tt_isdst)
229 timezone = -(ttisp->tt_gmtoff);
230#endif /* defined USG_COMPAT */
231#ifdef ALTZONE
232 if (i == 0 || ttisp->tt_isdst)
233 altzone = -(ttisp->tt_gmtoff);
234#endif /* defined ALTZONE */
235 }
236 /*
237 ** And to get the latest zone names into tzname. . .
238 */
239 for (i = 0; i < sp->timecnt; ++i) {
240 register const struct ttinfo * const ttisp =
241 &sp->ttis[
242 sp->types[i]];
243
244 tzname[ttisp->tt_isdst] =
221 (char *) &sp->chars[ttisp->tt_abbrind];
245 &sp->chars[ttisp->tt_abbrind];
222 }
223}
224
225static int
226tzload(name, sp)
227register const char * name;
228register struct state * const sp;
229{
230 register const char * p;
231 register int i;
232 register int fid;
233
234 if (name == NULL && (name = TZDEFAULT) == NULL)
235 return -1;
236 {
246 }
247}
248
249static int
250tzload(name, sp)
251register const char * name;
252register struct state * const sp;
253{
254 register const char * p;
255 register int i;
256 register int fid;
257
258 if (name == NULL && (name = TZDEFAULT) == NULL)
259 return -1;
260 {
237 register int doaccess;
261 register int doaccess;
262 /*
263 ** Section 4.9.1 of the C standard says that
264 ** "FILENAME_MAX expands to an integral constant expression
265 ** that is the sie needed for an array of char large enough
266 ** to hold the longest file name string that the implementation
267 ** guarantees can be opened."
268 */
238 char fullname[FILENAME_MAX + 1];
239
240 if (name[0] == ':')
241 ++name;
242 doaccess = name[0] == '/';
243 if (!doaccess) {
244 if ((p = TZDIR) == NULL)
245 return -1;
246 if ((strlen(p) + strlen(name) + 1) >= sizeof fullname)
247 return -1;
248 (void) strcpy(fullname, p);
249 (void) strcat(fullname, "/");
250 (void) strcat(fullname, name);
251 /*
252 ** Set doaccess if '.' (as in "../") shows up in name.
253 */
254 if (strchr(name, '.') != NULL)
255 doaccess = TRUE;
256 name = fullname;
257 }
269 char fullname[FILENAME_MAX + 1];
270
271 if (name[0] == ':')
272 ++name;
273 doaccess = name[0] == '/';
274 if (!doaccess) {
275 if ((p = TZDIR) == NULL)
276 return -1;
277 if ((strlen(p) + strlen(name) + 1) >= sizeof fullname)
278 return -1;
279 (void) strcpy(fullname, p);
280 (void) strcat(fullname, "/");
281 (void) strcat(fullname, name);
282 /*
283 ** Set doaccess if '.' (as in "../") shows up in name.
284 */
285 if (strchr(name, '.') != NULL)
286 doaccess = TRUE;
287 name = fullname;
288 }
258 if (doaccess && access(name, ACCESS_MODE) != 0)
289 if (doaccess && access(name, R_OK) != 0)
259 return -1;
260 if ((fid = open(name, OPEN_MODE)) == -1)
261 return -1;
262 }
263 {
290 return -1;
291 if ((fid = open(name, OPEN_MODE)) == -1)
292 return -1;
293 }
294 {
264 register const struct tzhead * tzhp;
265 char buf[sizeof *sp + sizeof *tzhp];
266 int ttisstdcnt;
295 struct tzhead * tzhp;
296 char buf[sizeof *sp + sizeof *tzhp];
297 int ttisstdcnt;
298 int ttisgmtcnt;
267
268 i = read(fid, buf, sizeof buf);
299
300 i = read(fid, buf, sizeof buf);
269 if (close(fid) != 0 || i < sizeof *tzhp)
301 if (close(fid) != 0)
270 return -1;
302 return -1;
271 tzhp = (struct tzhead *) buf;
272 ttisstdcnt = (int) detzcode(tzhp->tzh_ttisstdcnt);
273 sp->leapcnt = (int) detzcode(tzhp->tzh_leapcnt);
274 sp->timecnt = (int) detzcode(tzhp->tzh_timecnt);
275 sp->typecnt = (int) detzcode(tzhp->tzh_typecnt);
276 sp->charcnt = (int) detzcode(tzhp->tzh_charcnt);
303 p = buf;
304 p += sizeof tzhp->tzh_reserved;
305 ttisstdcnt = (int) detzcode(p);
306 p += 4;
307 ttisgmtcnt = (int) detzcode(p);
308 p += 4;
309 sp->leapcnt = (int) detzcode(p);
310 p += 4;
311 sp->timecnt = (int) detzcode(p);
312 p += 4;
313 sp->typecnt = (int) detzcode(p);
314 p += 4;
315 sp->charcnt = (int) detzcode(p);
316 p += 4;
277 if (sp->leapcnt < 0 || sp->leapcnt > TZ_MAX_LEAPS ||
278 sp->typecnt <= 0 || sp->typecnt > TZ_MAX_TYPES ||
279 sp->timecnt < 0 || sp->timecnt > TZ_MAX_TIMES ||
280 sp->charcnt < 0 || sp->charcnt > TZ_MAX_CHARS ||
317 if (sp->leapcnt < 0 || sp->leapcnt > TZ_MAX_LEAPS ||
318 sp->typecnt <= 0 || sp->typecnt > TZ_MAX_TYPES ||
319 sp->timecnt < 0 || sp->timecnt > TZ_MAX_TIMES ||
320 sp->charcnt < 0 || sp->charcnt > TZ_MAX_CHARS ||
281 (ttisstdcnt != sp->typecnt && ttisstdcnt != 0))
321 (ttisstdcnt != sp->typecnt && ttisstdcnt != 0) ||
322 (ttisgmtcnt != sp->typecnt && ttisgmtcnt != 0))
282 return -1;
323 return -1;
283 if (i < sizeof *tzhp +
284 sp->timecnt * (4 + sizeof (char)) +
285 sp->typecnt * (4 + 2 * sizeof (char)) +
286 sp->charcnt * sizeof (char) +
287 sp->leapcnt * 2 * 4 +
288 ttisstdcnt * sizeof (char))
324 if (i - (p - buf) < sp->timecnt * 4 + /* ats */
325 sp->timecnt + /* types */
326 sp->typecnt * (4 + 2) + /* ttinfos */
327 sp->charcnt + /* chars */
328 sp->leapcnt * (4 + 4) + /* lsinfos */
329 ttisstdcnt + /* ttisstds */
330 ttisgmtcnt) /* ttisgmts */
289 return -1;
331 return -1;
290 p = buf + sizeof *tzhp;
291 for (i = 0; i < sp->timecnt; ++i) {
292 sp->ats[i] = detzcode(p);
293 p += 4;
294 }
295 for (i = 0; i < sp->timecnt; ++i) {
296 sp->types[i] = (unsigned char) *p++;
297 if (sp->types[i] >= sp->typecnt)
298 return -1;
299 }
300 for (i = 0; i < sp->typecnt; ++i) {
301 register struct ttinfo * ttisp;
302
303 ttisp = &sp->ttis[i];
304 ttisp->tt_gmtoff = detzcode(p);
305 p += 4;
306 ttisp->tt_isdst = (unsigned char) *p++;
307 if (ttisp->tt_isdst != 0 && ttisp->tt_isdst != 1)
308 return -1;
309 ttisp->tt_abbrind = (unsigned char) *p++;
310 if (ttisp->tt_abbrind < 0 ||
311 ttisp->tt_abbrind > sp->charcnt)
312 return -1;
313 }
314 for (i = 0; i < sp->charcnt; ++i)
315 sp->chars[i] = *p++;
316 sp->chars[i] = '\0'; /* ensure '\0' at end */
317 for (i = 0; i < sp->leapcnt; ++i) {
318 register struct lsinfo * lsisp;
319
320 lsisp = &sp->lsis[i];
321 lsisp->ls_trans = detzcode(p);
322 p += 4;
323 lsisp->ls_corr = detzcode(p);
324 p += 4;
325 }
326 for (i = 0; i < sp->typecnt; ++i) {
327 register struct ttinfo * ttisp;
328
329 ttisp = &sp->ttis[i];
330 if (ttisstdcnt == 0)
331 ttisp->tt_ttisstd = FALSE;
332 else {
333 ttisp->tt_ttisstd = *p++;
334 if (ttisp->tt_ttisstd != TRUE &&
335 ttisp->tt_ttisstd != FALSE)
336 return -1;
337 }
338 }
332 for (i = 0; i < sp->timecnt; ++i) {
333 sp->ats[i] = detzcode(p);
334 p += 4;
335 }
336 for (i = 0; i < sp->timecnt; ++i) {
337 sp->types[i] = (unsigned char) *p++;
338 if (sp->types[i] >= sp->typecnt)
339 return -1;
340 }
341 for (i = 0; i < sp->typecnt; ++i) {
342 register struct ttinfo * ttisp;
343
344 ttisp = &sp->ttis[i];
345 ttisp->tt_gmtoff = detzcode(p);
346 p += 4;
347 ttisp->tt_isdst = (unsigned char) *p++;
348 if (ttisp->tt_isdst != 0 && ttisp->tt_isdst != 1)
349 return -1;
350 ttisp->tt_abbrind = (unsigned char) *p++;
351 if (ttisp->tt_abbrind < 0 ||
352 ttisp->tt_abbrind > sp->charcnt)
353 return -1;
354 }
355 for (i = 0; i < sp->charcnt; ++i)
356 sp->chars[i] = *p++;
357 sp->chars[i] = '\0'; /* ensure '\0' at end */
358 for (i = 0; i < sp->leapcnt; ++i) {
359 register struct lsinfo * lsisp;
360
361 lsisp = &sp->lsis[i];
362 lsisp->ls_trans = detzcode(p);
363 p += 4;
364 lsisp->ls_corr = detzcode(p);
365 p += 4;
366 }
367 for (i = 0; i < sp->typecnt; ++i) {
368 register struct ttinfo * ttisp;
369
370 ttisp = &sp->ttis[i];
371 if (ttisstdcnt == 0)
372 ttisp->tt_ttisstd = FALSE;
373 else {
374 ttisp->tt_ttisstd = *p++;
375 if (ttisp->tt_ttisstd != TRUE &&
376 ttisp->tt_ttisstd != FALSE)
377 return -1;
378 }
379 }
380 for (i = 0; i < sp->typecnt; ++i) {
381 register struct ttinfo * ttisp;
382
383 ttisp = &sp->ttis[i];
384 if (ttisgmtcnt == 0)
385 ttisp->tt_ttisgmt = FALSE;
386 else {
387 ttisp->tt_ttisgmt = *p++;
388 if (ttisp->tt_ttisgmt != TRUE &&
389 ttisp->tt_ttisgmt != FALSE)
390 return -1;
391 }
392 }
339 }
340 return 0;
341}
342
343static const int mon_lengths[2][MONSPERYEAR] = {
344 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
345 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
346};
347
348static const int year_lengths[2] = {
349 DAYSPERNYEAR, DAYSPERLYEAR
350};
351
352/*
353** Given a pointer into a time zone string, scan until a character that is not
354** a valid character in a zone name is found. Return a pointer to that
355** character.
356*/
357
358static const char *
359getzname(strp)
360register const char * strp;
361{
362 register char c;
363
364 while ((c = *strp) != '\0' && !isdigit(c) && c != ',' && c != '-' &&
365 c != '+')
366 ++strp;
367 return strp;
368}
369
370/*
371** Given a pointer into a time zone string, extract a number from that string.
372** Check that the number is within a specified range; if it is not, return
373** NULL.
374** Otherwise, return a pointer to the first character not part of the number.
375*/
376
377static const char *
378getnum(strp, nump, min, max)
379register const char * strp;
380int * const nump;
381const int min;
382const int max;
383{
384 register char c;
385 register int num;
386
387 if (strp == NULL || !isdigit(*strp))
388 return NULL;
389 num = 0;
390 while ((c = *strp) != '\0' && isdigit(c)) {
391 num = num * 10 + (c - '0');
392 if (num > max)
393 return NULL; /* illegal value */
394 ++strp;
395 }
396 if (num < min)
397 return NULL; /* illegal value */
398 *nump = num;
399 return strp;
400}
401
402/*
403** Given a pointer into a time zone string, extract a number of seconds,
404** in hh[:mm[:ss]] form, from the string.
405** If any error occurs, return NULL.
406** Otherwise, return a pointer to the first character not part of the number
407** of seconds.
408*/
409
410static const char *
411getsecs(strp, secsp)
412register const char * strp;
413long * const secsp;
414{
415 int num;
416
393 }
394 return 0;
395}
396
397static const int mon_lengths[2][MONSPERYEAR] = {
398 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
399 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
400};
401
402static const int year_lengths[2] = {
403 DAYSPERNYEAR, DAYSPERLYEAR
404};
405
406/*
407** Given a pointer into a time zone string, scan until a character that is not
408** a valid character in a zone name is found. Return a pointer to that
409** character.
410*/
411
412static const char *
413getzname(strp)
414register const char * strp;
415{
416 register char c;
417
418 while ((c = *strp) != '\0' && !isdigit(c) && c != ',' && c != '-' &&
419 c != '+')
420 ++strp;
421 return strp;
422}
423
424/*
425** Given a pointer into a time zone string, extract a number from that string.
426** Check that the number is within a specified range; if it is not, return
427** NULL.
428** Otherwise, return a pointer to the first character not part of the number.
429*/
430
431static const char *
432getnum(strp, nump, min, max)
433register const char * strp;
434int * const nump;
435const int min;
436const int max;
437{
438 register char c;
439 register int num;
440
441 if (strp == NULL || !isdigit(*strp))
442 return NULL;
443 num = 0;
444 while ((c = *strp) != '\0' && isdigit(c)) {
445 num = num * 10 + (c - '0');
446 if (num > max)
447 return NULL; /* illegal value */
448 ++strp;
449 }
450 if (num < min)
451 return NULL; /* illegal value */
452 *nump = num;
453 return strp;
454}
455
456/*
457** Given a pointer into a time zone string, extract a number of seconds,
458** in hh[:mm[:ss]] form, from the string.
459** If any error occurs, return NULL.
460** Otherwise, return a pointer to the first character not part of the number
461** of seconds.
462*/
463
464static const char *
465getsecs(strp, secsp)
466register const char * strp;
467long * const secsp;
468{
469 int num;
470
417 strp = getnum(strp, &num, 0, HOURSPERDAY);
471 /*
472 ** `HOURSPERDAY * DAYSPERWEEK - 1' allows quasi-Posix rules like
473 ** "M10.4.6/26", which does not conform to Posix,
474 ** but which specifies the equivalent of
475 ** ``02:00 on the first Sunday on or after 23 Oct''.
476 */
477 strp = getnum(strp, &num, 0, HOURSPERDAY * DAYSPERWEEK - 1);
418 if (strp == NULL)
419 return NULL;
478 if (strp == NULL)
479 return NULL;
420 *secsp = num * SECSPERHOUR;
480 *secsp = num * (long) SECSPERHOUR;
421 if (*strp == ':') {
422 ++strp;
423 strp = getnum(strp, &num, 0, MINSPERHOUR - 1);
424 if (strp == NULL)
425 return NULL;
426 *secsp += num * SECSPERMIN;
427 if (*strp == ':') {
428 ++strp;
481 if (*strp == ':') {
482 ++strp;
483 strp = getnum(strp, &num, 0, MINSPERHOUR - 1);
484 if (strp == NULL)
485 return NULL;
486 *secsp += num * SECSPERMIN;
487 if (*strp == ':') {
488 ++strp;
429 strp = getnum(strp, &num, 0, SECSPERMIN - 1);
489 /* `SECSPERMIN' allows for leap seconds. */
490 strp = getnum(strp, &num, 0, SECSPERMIN);
430 if (strp == NULL)
431 return NULL;
432 *secsp += num;
433 }
434 }
435 return strp;
436}
437
438/*
439** Given a pointer into a time zone string, extract an offset, in
440** [+-]hh[:mm[:ss]] form, from the string.
441** If any error occurs, return NULL.
442** Otherwise, return a pointer to the first character not part of the time.
443*/
444
445static const char *
446getoffset(strp, offsetp)
447register const char * strp;
448long * const offsetp;
449{
450 register int neg;
451
452 if (*strp == '-') {
453 neg = 1;
454 ++strp;
455 } else if (isdigit(*strp) || *strp++ == '+')
456 neg = 0;
457 else return NULL; /* illegal offset */
458 strp = getsecs(strp, offsetp);
459 if (strp == NULL)
460 return NULL; /* illegal time */
461 if (neg)
462 *offsetp = -*offsetp;
463 return strp;
464}
465
466/*
467** Given a pointer into a time zone string, extract a rule in the form
468** date[/time]. See POSIX section 8 for the format of "date" and "time".
469** If a valid rule is not found, return NULL.
470** Otherwise, return a pointer to the first character not part of the rule.
471*/
472
473static const char *
474getrule(strp, rulep)
475const char * strp;
476register struct rule * const rulep;
477{
478 if (*strp == 'J') {
479 /*
480 ** Julian day.
481 */
482 rulep->r_type = JULIAN_DAY;
483 ++strp;
484 strp = getnum(strp, &rulep->r_day, 1, DAYSPERNYEAR);
485 } else if (*strp == 'M') {
486 /*
487 ** Month, week, day.
488 */
489 rulep->r_type = MONTH_NTH_DAY_OF_WEEK;
490 ++strp;
491 strp = getnum(strp, &rulep->r_mon, 1, MONSPERYEAR);
492 if (strp == NULL)
493 return NULL;
494 if (*strp++ != '.')
495 return NULL;
496 strp = getnum(strp, &rulep->r_week, 1, 5);
497 if (strp == NULL)
498 return NULL;
499 if (*strp++ != '.')
500 return NULL;
501 strp = getnum(strp, &rulep->r_day, 0, DAYSPERWEEK - 1);
502 } else if (isdigit(*strp)) {
503 /*
504 ** Day of year.
505 */
506 rulep->r_type = DAY_OF_YEAR;
507 strp = getnum(strp, &rulep->r_day, 0, DAYSPERLYEAR - 1);
508 } else return NULL; /* invalid format */
509 if (strp == NULL)
510 return NULL;
511 if (*strp == '/') {
512 /*
513 ** Time specified.
514 */
515 ++strp;
516 strp = getsecs(strp, &rulep->r_time);
517 } else rulep->r_time = 2 * SECSPERHOUR; /* default = 2:00:00 */
518 return strp;
519}
520
521/*
522** Given the Epoch-relative time of January 1, 00:00:00 GMT, in a year, the
523** year, a rule, and the offset from GMT at the time that rule takes effect,
524** calculate the Epoch-relative time that rule takes effect.
525*/
526
527static time_t
528transtime(janfirst, year, rulep, offset)
529const time_t janfirst;
530const int year;
531register const struct rule * const rulep;
532const long offset;
533{
534 register int leapyear;
535 register time_t value;
536 register int i;
537 int d, m1, yy0, yy1, yy2, dow;
538
491 if (strp == NULL)
492 return NULL;
493 *secsp += num;
494 }
495 }
496 return strp;
497}
498
499/*
500** Given a pointer into a time zone string, extract an offset, in
501** [+-]hh[:mm[:ss]] form, from the string.
502** If any error occurs, return NULL.
503** Otherwise, return a pointer to the first character not part of the time.
504*/
505
506static const char *
507getoffset(strp, offsetp)
508register const char * strp;
509long * const offsetp;
510{
511 register int neg;
512
513 if (*strp == '-') {
514 neg = 1;
515 ++strp;
516 } else if (isdigit(*strp) || *strp++ == '+')
517 neg = 0;
518 else return NULL; /* illegal offset */
519 strp = getsecs(strp, offsetp);
520 if (strp == NULL)
521 return NULL; /* illegal time */
522 if (neg)
523 *offsetp = -*offsetp;
524 return strp;
525}
526
527/*
528** Given a pointer into a time zone string, extract a rule in the form
529** date[/time]. See POSIX section 8 for the format of "date" and "time".
530** If a valid rule is not found, return NULL.
531** Otherwise, return a pointer to the first character not part of the rule.
532*/
533
534static const char *
535getrule(strp, rulep)
536const char * strp;
537register struct rule * const rulep;
538{
539 if (*strp == 'J') {
540 /*
541 ** Julian day.
542 */
543 rulep->r_type = JULIAN_DAY;
544 ++strp;
545 strp = getnum(strp, &rulep->r_day, 1, DAYSPERNYEAR);
546 } else if (*strp == 'M') {
547 /*
548 ** Month, week, day.
549 */
550 rulep->r_type = MONTH_NTH_DAY_OF_WEEK;
551 ++strp;
552 strp = getnum(strp, &rulep->r_mon, 1, MONSPERYEAR);
553 if (strp == NULL)
554 return NULL;
555 if (*strp++ != '.')
556 return NULL;
557 strp = getnum(strp, &rulep->r_week, 1, 5);
558 if (strp == NULL)
559 return NULL;
560 if (*strp++ != '.')
561 return NULL;
562 strp = getnum(strp, &rulep->r_day, 0, DAYSPERWEEK - 1);
563 } else if (isdigit(*strp)) {
564 /*
565 ** Day of year.
566 */
567 rulep->r_type = DAY_OF_YEAR;
568 strp = getnum(strp, &rulep->r_day, 0, DAYSPERLYEAR - 1);
569 } else return NULL; /* invalid format */
570 if (strp == NULL)
571 return NULL;
572 if (*strp == '/') {
573 /*
574 ** Time specified.
575 */
576 ++strp;
577 strp = getsecs(strp, &rulep->r_time);
578 } else rulep->r_time = 2 * SECSPERHOUR; /* default = 2:00:00 */
579 return strp;
580}
581
582/*
583** Given the Epoch-relative time of January 1, 00:00:00 GMT, in a year, the
584** year, a rule, and the offset from GMT at the time that rule takes effect,
585** calculate the Epoch-relative time that rule takes effect.
586*/
587
588static time_t
589transtime(janfirst, year, rulep, offset)
590const time_t janfirst;
591const int year;
592register const struct rule * const rulep;
593const long offset;
594{
595 register int leapyear;
596 register time_t value;
597 register int i;
598 int d, m1, yy0, yy1, yy2, dow;
599
600 INITIALIZE(value);
539 leapyear = isleap(year);
540 switch (rulep->r_type) {
541
542 case JULIAN_DAY:
543 /*
544 ** Jn - Julian day, 1 == January 1, 60 == March 1 even in leap
545 ** years.
546 ** In non-leap years, or if the day number is 59 or less, just
547 ** add SECSPERDAY times the day number-1 to the time of
548 ** January 1, midnight, to get the day.
549 */
550 value = janfirst + (rulep->r_day - 1) * SECSPERDAY;
551 if (leapyear && rulep->r_day >= 60)
552 value += SECSPERDAY;
553 break;
554
555 case DAY_OF_YEAR:
556 /*
557 ** n - day of year.
558 ** Just add SECSPERDAY times the day number to the time of
559 ** January 1, midnight, to get the day.
560 */
561 value = janfirst + rulep->r_day * SECSPERDAY;
562 break;
563
564 case MONTH_NTH_DAY_OF_WEEK:
565 /*
566 ** Mm.n.d - nth "dth day" of month m.
567 */
568 value = janfirst;
569 for (i = 0; i < rulep->r_mon - 1; ++i)
570 value += mon_lengths[leapyear][i] * SECSPERDAY;
571
572 /*
573 ** Use Zeller's Congruence to get day-of-week of first day of
574 ** month.
575 */
576 m1 = (rulep->r_mon + 9) % 12 + 1;
577 yy0 = (rulep->r_mon <= 2) ? (year - 1) : year;
578 yy1 = yy0 / 100;
579 yy2 = yy0 % 100;
580 dow = ((26 * m1 - 2) / 10 +
581 1 + yy2 + yy2 / 4 + yy1 / 4 - 2 * yy1) % 7;
582 if (dow < 0)
583 dow += DAYSPERWEEK;
584
585 /*
586 ** "dow" is the day-of-week of the first day of the month. Get
587 ** the day-of-month (zero-origin) of the first "dow" day of the
588 ** month.
589 */
590 d = rulep->r_day - dow;
591 if (d < 0)
592 d += DAYSPERWEEK;
593 for (i = 1; i < rulep->r_week; ++i) {
594 if (d + DAYSPERWEEK >=
595 mon_lengths[leapyear][rulep->r_mon - 1])
596 break;
597 d += DAYSPERWEEK;
598 }
599
600 /*
601 ** "d" is the day-of-month (zero-origin) of the day we want.
602 */
603 value += d * SECSPERDAY;
604 break;
605 }
606
607 /*
608 ** "value" is the Epoch-relative time of 00:00:00 GMT on the day in
609 ** question. To get the Epoch-relative time of the specified local
610 ** time on that day, add the transition time and the current offset
611 ** from GMT.
612 */
613 return value + rulep->r_time + offset;
614}
615
616/*
617** Given a POSIX section 8-style TZ string, fill in the rule tables as
618** appropriate.
619*/
620
621static int
622tzparse(name, sp, lastditch)
623const char * name;
624register struct state * const sp;
625const int lastditch;
626{
627 const char * stdname;
628 const char * dstname;
601 leapyear = isleap(year);
602 switch (rulep->r_type) {
603
604 case JULIAN_DAY:
605 /*
606 ** Jn - Julian day, 1 == January 1, 60 == March 1 even in leap
607 ** years.
608 ** In non-leap years, or if the day number is 59 or less, just
609 ** add SECSPERDAY times the day number-1 to the time of
610 ** January 1, midnight, to get the day.
611 */
612 value = janfirst + (rulep->r_day - 1) * SECSPERDAY;
613 if (leapyear && rulep->r_day >= 60)
614 value += SECSPERDAY;
615 break;
616
617 case DAY_OF_YEAR:
618 /*
619 ** n - day of year.
620 ** Just add SECSPERDAY times the day number to the time of
621 ** January 1, midnight, to get the day.
622 */
623 value = janfirst + rulep->r_day * SECSPERDAY;
624 break;
625
626 case MONTH_NTH_DAY_OF_WEEK:
627 /*
628 ** Mm.n.d - nth "dth day" of month m.
629 */
630 value = janfirst;
631 for (i = 0; i < rulep->r_mon - 1; ++i)
632 value += mon_lengths[leapyear][i] * SECSPERDAY;
633
634 /*
635 ** Use Zeller's Congruence to get day-of-week of first day of
636 ** month.
637 */
638 m1 = (rulep->r_mon + 9) % 12 + 1;
639 yy0 = (rulep->r_mon <= 2) ? (year - 1) : year;
640 yy1 = yy0 / 100;
641 yy2 = yy0 % 100;
642 dow = ((26 * m1 - 2) / 10 +
643 1 + yy2 + yy2 / 4 + yy1 / 4 - 2 * yy1) % 7;
644 if (dow < 0)
645 dow += DAYSPERWEEK;
646
647 /*
648 ** "dow" is the day-of-week of the first day of the month. Get
649 ** the day-of-month (zero-origin) of the first "dow" day of the
650 ** month.
651 */
652 d = rulep->r_day - dow;
653 if (d < 0)
654 d += DAYSPERWEEK;
655 for (i = 1; i < rulep->r_week; ++i) {
656 if (d + DAYSPERWEEK >=
657 mon_lengths[leapyear][rulep->r_mon - 1])
658 break;
659 d += DAYSPERWEEK;
660 }
661
662 /*
663 ** "d" is the day-of-month (zero-origin) of the day we want.
664 */
665 value += d * SECSPERDAY;
666 break;
667 }
668
669 /*
670 ** "value" is the Epoch-relative time of 00:00:00 GMT on the day in
671 ** question. To get the Epoch-relative time of the specified local
672 ** time on that day, add the transition time and the current offset
673 ** from GMT.
674 */
675 return value + rulep->r_time + offset;
676}
677
678/*
679** Given a POSIX section 8-style TZ string, fill in the rule tables as
680** appropriate.
681*/
682
683static int
684tzparse(name, sp, lastditch)
685const char * name;
686register struct state * const sp;
687const int lastditch;
688{
689 const char * stdname;
690 const char * dstname;
629 int stdlen;
630 int dstlen;
691 size_t stdlen;
692 size_t dstlen;
631 long stdoffset;
632 long dstoffset;
633 register time_t * atp;
634 register unsigned char * typep;
635 register char * cp;
636 register int load_result;
637
693 long stdoffset;
694 long dstoffset;
695 register time_t * atp;
696 register unsigned char * typep;
697 register char * cp;
698 register int load_result;
699
700 INITIALIZE(dstname);
638 stdname = name;
639 if (lastditch) {
640 stdlen = strlen(name); /* length of standard zone name */
641 name += stdlen;
642 if (stdlen >= sizeof sp->chars)
643 stdlen = (sizeof sp->chars) - 1;
644 } else {
645 name = getzname(name);
646 stdlen = name - stdname;
647 if (stdlen < 3)
648 return -1;
649 }
650 if (*name == '\0')
651 return -1; /* was "stdoffset = 0;" */
652 else {
653 name = getoffset(name, &stdoffset);
654 if (name == NULL)
655 return -1;
656 }
657 load_result = tzload(TZDEFRULES, sp);
658 if (load_result != 0)
659 sp->leapcnt = 0; /* so, we're off a little */
660 if (*name != '\0') {
661 dstname = name;
662 name = getzname(name);
663 dstlen = name - dstname; /* length of DST zone name */
664 if (dstlen < 3)
665 return -1;
666 if (*name != '\0' && *name != ',' && *name != ';') {
667 name = getoffset(name, &dstoffset);
668 if (name == NULL)
669 return -1;
670 } else dstoffset = stdoffset - SECSPERHOUR;
671 if (*name == ',' || *name == ';') {
672 struct rule start;
673 struct rule end;
674 register int year;
675 register time_t janfirst;
676 time_t starttime;
677 time_t endtime;
678
679 ++name;
680 if ((name = getrule(name, &start)) == NULL)
681 return -1;
682 if (*name++ != ',')
683 return -1;
684 if ((name = getrule(name, &end)) == NULL)
685 return -1;
686 if (*name != '\0')
687 return -1;
688 sp->typecnt = 2; /* standard time and DST */
689 /*
690 ** Two transitions per year, from EPOCH_YEAR to 2037.
691 */
692 sp->timecnt = 2 * (2037 - EPOCH_YEAR + 1);
693 if (sp->timecnt > TZ_MAX_TIMES)
694 return -1;
695 sp->ttis[0].tt_gmtoff = -dstoffset;
696 sp->ttis[0].tt_isdst = 1;
697 sp->ttis[0].tt_abbrind = stdlen + 1;
698 sp->ttis[1].tt_gmtoff = -stdoffset;
699 sp->ttis[1].tt_isdst = 0;
700 sp->ttis[1].tt_abbrind = 0;
701 atp = sp->ats;
702 typep = sp->types;
703 janfirst = 0;
704 for (year = EPOCH_YEAR; year <= 2037; ++year) {
705 starttime = transtime(janfirst, year, &start,
706 stdoffset);
707 endtime = transtime(janfirst, year, &end,
708 dstoffset);
709 if (starttime > endtime) {
710 *atp++ = endtime;
711 *typep++ = 1; /* DST ends */
712 *atp++ = starttime;
713 *typep++ = 0; /* DST begins */
714 } else {
715 *atp++ = starttime;
716 *typep++ = 0; /* DST begins */
717 *atp++ = endtime;
718 *typep++ = 1; /* DST ends */
719 }
720 janfirst += year_lengths[isleap(year)] *
721 SECSPERDAY;
722 }
723 } else {
701 stdname = name;
702 if (lastditch) {
703 stdlen = strlen(name); /* length of standard zone name */
704 name += stdlen;
705 if (stdlen >= sizeof sp->chars)
706 stdlen = (sizeof sp->chars) - 1;
707 } else {
708 name = getzname(name);
709 stdlen = name - stdname;
710 if (stdlen < 3)
711 return -1;
712 }
713 if (*name == '\0')
714 return -1; /* was "stdoffset = 0;" */
715 else {
716 name = getoffset(name, &stdoffset);
717 if (name == NULL)
718 return -1;
719 }
720 load_result = tzload(TZDEFRULES, sp);
721 if (load_result != 0)
722 sp->leapcnt = 0; /* so, we're off a little */
723 if (*name != '\0') {
724 dstname = name;
725 name = getzname(name);
726 dstlen = name - dstname; /* length of DST zone name */
727 if (dstlen < 3)
728 return -1;
729 if (*name != '\0' && *name != ',' && *name != ';') {
730 name = getoffset(name, &dstoffset);
731 if (name == NULL)
732 return -1;
733 } else dstoffset = stdoffset - SECSPERHOUR;
734 if (*name == ',' || *name == ';') {
735 struct rule start;
736 struct rule end;
737 register int year;
738 register time_t janfirst;
739 time_t starttime;
740 time_t endtime;
741
742 ++name;
743 if ((name = getrule(name, &start)) == NULL)
744 return -1;
745 if (*name++ != ',')
746 return -1;
747 if ((name = getrule(name, &end)) == NULL)
748 return -1;
749 if (*name != '\0')
750 return -1;
751 sp->typecnt = 2; /* standard time and DST */
752 /*
753 ** Two transitions per year, from EPOCH_YEAR to 2037.
754 */
755 sp->timecnt = 2 * (2037 - EPOCH_YEAR + 1);
756 if (sp->timecnt > TZ_MAX_TIMES)
757 return -1;
758 sp->ttis[0].tt_gmtoff = -dstoffset;
759 sp->ttis[0].tt_isdst = 1;
760 sp->ttis[0].tt_abbrind = stdlen + 1;
761 sp->ttis[1].tt_gmtoff = -stdoffset;
762 sp->ttis[1].tt_isdst = 0;
763 sp->ttis[1].tt_abbrind = 0;
764 atp = sp->ats;
765 typep = sp->types;
766 janfirst = 0;
767 for (year = EPOCH_YEAR; year <= 2037; ++year) {
768 starttime = transtime(janfirst, year, &start,
769 stdoffset);
770 endtime = transtime(janfirst, year, &end,
771 dstoffset);
772 if (starttime > endtime) {
773 *atp++ = endtime;
774 *typep++ = 1; /* DST ends */
775 *atp++ = starttime;
776 *typep++ = 0; /* DST begins */
777 } else {
778 *atp++ = starttime;
779 *typep++ = 0; /* DST begins */
780 *atp++ = endtime;
781 *typep++ = 1; /* DST ends */
782 }
783 janfirst += year_lengths[isleap(year)] *
784 SECSPERDAY;
785 }
786 } else {
724 int sawstd;
725 int sawdst;
726 long stdfix;
727 long dstfix;
728 long oldfix;
729 int isdst;
787 register long theirstdoffset;
788 register long theirdstoffset;
789 register long theiroffset;
790 register int isdst;
730 register int i;
791 register int i;
792 register int j;
731
732 if (*name != '\0')
733 return -1;
734 if (load_result != 0)
735 return -1;
736 /*
793
794 if (*name != '\0')
795 return -1;
796 if (load_result != 0)
797 return -1;
798 /*
737 ** Compute the difference between the real and
738 ** prototype standard and summer time offsets
739 ** from GMT, and put the real standard and summer
740 ** time offsets into the rules in place of the
741 ** prototype offsets.
799 ** Initial values of theirstdoffset and theirdstoffset.
742 */
800 */
743 sawstd = FALSE;
744 sawdst = FALSE;
745 stdfix = 0;
746 dstfix = 0;
747 for (i = 0; i < sp->typecnt; ++i) {
748 if (sp->ttis[i].tt_isdst) {
749 oldfix = dstfix;
750 dstfix = sp->ttis[i].tt_gmtoff +
751 dstoffset;
752 if (sawdst && (oldfix != dstfix))
753 return -1;
754 sp->ttis[i].tt_gmtoff = -dstoffset;
755 sp->ttis[i].tt_abbrind = stdlen + 1;
756 sawdst = TRUE;
757 } else {
758 oldfix = stdfix;
759 stdfix = sp->ttis[i].tt_gmtoff +
760 stdoffset;
761 if (sawstd && (oldfix != stdfix))
762 return -1;
763 sp->ttis[i].tt_gmtoff = -stdoffset;
764 sp->ttis[i].tt_abbrind = 0;
765 sawstd = TRUE;
801 theirstdoffset = 0;
802 for (i = 0; i < sp->timecnt; ++i) {
803 j = sp->types[i];
804 if (!sp->ttis[j].tt_isdst) {
805 theirstdoffset = -sp->ttis[j].tt_gmtoff;
806 break;
766 }
767 }
807 }
808 }
809 theirdstoffset = 0;
810 for (i = 0; i < sp->timecnt; ++i) {
811 j = sp->types[i];
812 if (sp->ttis[j].tt_isdst) {
813 theirdstoffset = -sp->ttis[j].tt_gmtoff;
814 break;
815 }
816 }
768 /*
817 /*
769 ** Make sure we have both standard and summer time.
818 ** Initially we're assumed to be in standard time.
770 */
819 */
771 if (!sawdst || !sawstd)
772 return -1;
820 isdst = FALSE;
821 theiroffset = theirstdoffset;
773 /*
822 /*
774 ** Now correct the transition times by shifting
775 ** them by the difference between the real and
776 ** prototype offsets. Note that this difference
777 ** can be different in standard and summer time;
778 ** the prototype probably has a 1-hour difference
779 ** between standard and summer time, but a different
780 ** difference can be specified in TZ.
823 ** Now juggle transition times and types
824 ** tracking offsets as you do.
781 */
825 */
782 isdst = FALSE; /* we start in standard time */
783 for (i = 0; i < sp->timecnt; ++i) {
826 for (i = 0; i < sp->timecnt; ++i) {
784 register const struct ttinfo * ttisp;
785
786 /*
787 ** If summer time is in effect, and the
788 ** transition time was not specified as
789 ** standard time, add the summer time
790 ** offset to the transition time;
791 ** otherwise, add the standard time offset
792 ** to the transition time.
793 */
794 ttisp = &sp->ttis[sp->types[i]];
795 sp->ats[i] +=
796 (isdst && !ttisp->tt_ttisstd) ?
797 dstfix : stdfix;
798 isdst = ttisp->tt_isdst;
827 j = sp->types[i];
828 sp->types[i] = sp->ttis[j].tt_isdst;
829 if (sp->ttis[j].tt_ttisgmt) {
830 /* No adjustment to transition time */
831 } else {
832 /*
833 ** If summer time is in effect, and the
834 ** transition time was not specified as
835 ** standard time, add the summer time
836 ** offset to the transition time;
837 ** otherwise, add the standard time
838 ** offset to the transition time.
839 */
840 /*
841 ** Transitions from DST to DDST
842 ** will effectively disappear since
843 ** POSIX provides for only one DST
844 ** offset.
845 */
846 if (isdst && !sp->ttis[j].tt_ttisstd) {
847 sp->ats[i] += dstoffset -
848 theirdstoffset;
849 } else {
850 sp->ats[i] += stdoffset -
851 theirstdoffset;
852 }
853 }
854 theiroffset = -sp->ttis[j].tt_gmtoff;
855 if (sp->ttis[j].tt_isdst)
856 theirdstoffset = theiroffset;
857 else theirstdoffset = theiroffset;
799 }
858 }
859 /*
860 ** Finally, fill in ttis.
861 ** ttisstd and ttisgmt need not be handled.
862 */
863 sp->ttis[0].tt_gmtoff = -stdoffset;
864 sp->ttis[0].tt_isdst = FALSE;
865 sp->ttis[0].tt_abbrind = 0;
866 sp->ttis[1].tt_gmtoff = -dstoffset;
867 sp->ttis[1].tt_isdst = TRUE;
868 sp->ttis[1].tt_abbrind = stdlen + 1;
800 }
801 } else {
802 dstlen = 0;
803 sp->typecnt = 1; /* only standard time */
804 sp->timecnt = 0;
805 sp->ttis[0].tt_gmtoff = -stdoffset;
806 sp->ttis[0].tt_isdst = 0;
807 sp->ttis[0].tt_abbrind = 0;
808 }
809 sp->charcnt = stdlen + 1;
810 if (dstlen != 0)
811 sp->charcnt += dstlen + 1;
812 if (sp->charcnt > sizeof sp->chars)
813 return -1;
814 cp = sp->chars;
815 (void) strncpy(cp, stdname, stdlen);
816 cp += stdlen;
817 *cp++ = '\0';
818 if (dstlen != 0) {
819 (void) strncpy(cp, dstname, dstlen);
820 *(cp + dstlen) = '\0';
821 }
822 return 0;
823}
824
825static void
826gmtload(sp)
827struct state * const sp;
828{
869 }
870 } else {
871 dstlen = 0;
872 sp->typecnt = 1; /* only standard time */
873 sp->timecnt = 0;
874 sp->ttis[0].tt_gmtoff = -stdoffset;
875 sp->ttis[0].tt_isdst = 0;
876 sp->ttis[0].tt_abbrind = 0;
877 }
878 sp->charcnt = stdlen + 1;
879 if (dstlen != 0)
880 sp->charcnt += dstlen + 1;
881 if (sp->charcnt > sizeof sp->chars)
882 return -1;
883 cp = sp->chars;
884 (void) strncpy(cp, stdname, stdlen);
885 cp += stdlen;
886 *cp++ = '\0';
887 if (dstlen != 0) {
888 (void) strncpy(cp, dstname, dstlen);
889 *(cp + dstlen) = '\0';
890 }
891 return 0;
892}
893
894static void
895gmtload(sp)
896struct state * const sp;
897{
829 if (tzload(GMT, sp) != 0)
830 (void) tzparse(GMT, sp, TRUE);
898 if (tzload(gmt, sp) != 0)
899 (void) tzparse(gmt, sp, TRUE);
831}
832
833#ifndef STD_INSPIRED
900}
901
902#ifndef STD_INSPIRED
903/*
904** A non-static declaration of tzsetwall in a system header file
905** may cause a warning about this upcoming static declaration...
906*/
834static
835#endif /* !defined STD_INSPIRED */
836void
907static
908#endif /* !defined STD_INSPIRED */
909void
837tzsetwall()
910tzsetwall P((void))
838{
911{
839 lcl_is_set = TRUE;
912 if (lcl_is_set < 0)
913 return;
914 lcl_is_set = -1;
915
840#ifdef ALL_STATE
841 if (lclptr == NULL) {
842 lclptr = (struct state *) malloc(sizeof *lclptr);
843 if (lclptr == NULL) {
844 settzname(); /* all we can do */
845 return;
846 }
847 }
848#endif /* defined ALL_STATE */
849 if (tzload((char *) NULL, lclptr) != 0)
850 gmtload(lclptr);
851 settzname();
852}
853
854void
916#ifdef ALL_STATE
917 if (lclptr == NULL) {
918 lclptr = (struct state *) malloc(sizeof *lclptr);
919 if (lclptr == NULL) {
920 settzname(); /* all we can do */
921 return;
922 }
923 }
924#endif /* defined ALL_STATE */
925 if (tzload((char *) NULL, lclptr) != 0)
926 gmtload(lclptr);
927 settzname();
928}
929
930void
855tzset()
931tzset P((void))
856{
857 register const char * name;
858
859 name = getenv("TZ");
860 if (name == NULL) {
861 tzsetwall();
862 return;
863 }
932{
933 register const char * name;
934
935 name = getenv("TZ");
936 if (name == NULL) {
937 tzsetwall();
938 return;
939 }
864 lcl_is_set = TRUE;
940
941 if (lcl_is_set > 0 && strcmp(lcl_TZname, name) == 0)
942 return;
943 lcl_is_set = (strlen(name) < sizeof(lcl_TZname));
944 if (lcl_is_set)
945 (void) strcpy(lcl_TZname, name);
946
865#ifdef ALL_STATE
866 if (lclptr == NULL) {
867 lclptr = (struct state *) malloc(sizeof *lclptr);
868 if (lclptr == NULL) {
869 settzname(); /* all we can do */
870 return;
871 }
872 }
873#endif /* defined ALL_STATE */
874 if (*name == '\0') {
875 /*
876 ** User wants it fast rather than right.
877 */
878 lclptr->leapcnt = 0; /* so, we're off a little */
879 lclptr->timecnt = 0;
880 lclptr->ttis[0].tt_gmtoff = 0;
881 lclptr->ttis[0].tt_abbrind = 0;
947#ifdef ALL_STATE
948 if (lclptr == NULL) {
949 lclptr = (struct state *) malloc(sizeof *lclptr);
950 if (lclptr == NULL) {
951 settzname(); /* all we can do */
952 return;
953 }
954 }
955#endif /* defined ALL_STATE */
956 if (*name == '\0') {
957 /*
958 ** User wants it fast rather than right.
959 */
960 lclptr->leapcnt = 0; /* so, we're off a little */
961 lclptr->timecnt = 0;
962 lclptr->ttis[0].tt_gmtoff = 0;
963 lclptr->ttis[0].tt_abbrind = 0;
882 (void) strcpy(lclptr->chars, GMT);
964 (void) strcpy(lclptr->chars, gmt);
883 } else if (tzload(name, lclptr) != 0)
884 if (name[0] == ':' || tzparse(name, lclptr, FALSE) != 0)
885 (void) gmtload(lclptr);
886 settzname();
887}
888
889/*
890** The easy way to behave "as if no library function calls" localtime
891** is to not call it--so we drop its guts into "localsub", which can be
892** freely called. (And no, the PANS doesn't require the above behavior--
893** but it *is* desirable.)
894**
895** The unused offset argument is for the benefit of mktime variants.
896*/
897
898/*ARGSUSED*/
899static void
900localsub(timep, offset, tmp)
901const time_t * const timep;
902const long offset;
903struct tm * const tmp;
904{
965 } else if (tzload(name, lclptr) != 0)
966 if (name[0] == ':' || tzparse(name, lclptr, FALSE) != 0)
967 (void) gmtload(lclptr);
968 settzname();
969}
970
971/*
972** The easy way to behave "as if no library function calls" localtime
973** is to not call it--so we drop its guts into "localsub", which can be
974** freely called. (And no, the PANS doesn't require the above behavior--
975** but it *is* desirable.)
976**
977** The unused offset argument is for the benefit of mktime variants.
978*/
979
980/*ARGSUSED*/
981static void
982localsub(timep, offset, tmp)
983const time_t * const timep;
984const long offset;
985struct tm * const tmp;
986{
905 register const struct state * sp;
987 register struct state * sp;
906 register const struct ttinfo * ttisp;
907 register int i;
908 const time_t t = *timep;
909
988 register const struct ttinfo * ttisp;
989 register int i;
990 const time_t t = *timep;
991
910 if (!lcl_is_set)
911 tzset();
912 sp = lclptr;
913#ifdef ALL_STATE
914 if (sp == NULL) {
915 gmtsub(timep, offset, tmp);
916 return;
917 }
918#endif /* defined ALL_STATE */
919 if (sp->timecnt == 0 || t < sp->ats[0]) {
920 i = 0;
921 while (sp->ttis[i].tt_isdst)
922 if (++i >= sp->typecnt) {
923 i = 0;
924 break;
925 }
926 } else {
927 for (i = 1; i < sp->timecnt; ++i)
928 if (t < sp->ats[i])
929 break;
930 i = sp->types[i - 1];
931 }
932 ttisp = &sp->ttis[i];
933 /*
934 ** To get (wrong) behavior that's compatible with System V Release 2.0
935 ** you'd replace the statement below with
936 ** t += ttisp->tt_gmtoff;
937 ** timesub(&t, 0L, sp, tmp);
938 */
939 timesub(&t, ttisp->tt_gmtoff, sp, tmp);
940 tmp->tm_isdst = ttisp->tt_isdst;
992 sp = lclptr;
993#ifdef ALL_STATE
994 if (sp == NULL) {
995 gmtsub(timep, offset, tmp);
996 return;
997 }
998#endif /* defined ALL_STATE */
999 if (sp->timecnt == 0 || t < sp->ats[0]) {
1000 i = 0;
1001 while (sp->ttis[i].tt_isdst)
1002 if (++i >= sp->typecnt) {
1003 i = 0;
1004 break;
1005 }
1006 } else {
1007 for (i = 1; i < sp->timecnt; ++i)
1008 if (t < sp->ats[i])
1009 break;
1010 i = sp->types[i - 1];
1011 }
1012 ttisp = &sp->ttis[i];
1013 /*
1014 ** To get (wrong) behavior that's compatible with System V Release 2.0
1015 ** you'd replace the statement below with
1016 ** t += ttisp->tt_gmtoff;
1017 ** timesub(&t, 0L, sp, tmp);
1018 */
1019 timesub(&t, ttisp->tt_gmtoff, sp, tmp);
1020 tmp->tm_isdst = ttisp->tt_isdst;
941 tzname[tmp->tm_isdst] = (char *) &sp->chars[ttisp->tt_abbrind];
1021 tzname[tmp->tm_isdst] = &sp->chars[ttisp->tt_abbrind];
942#ifdef TM_ZONE
1022#ifdef TM_ZONE
943 tmp->TM_ZONE = (char *)&sp->chars[ttisp->tt_abbrind];
1023 tmp->TM_ZONE = &sp->chars[ttisp->tt_abbrind];
944#endif /* defined TM_ZONE */
945}
946
947struct tm *
948localtime(timep)
949const time_t * const timep;
950{
1024#endif /* defined TM_ZONE */
1025}
1026
1027struct tm *
1028localtime(timep)
1029const time_t * const timep;
1030{
951 static struct tm tm;
952
1031 tzset();
953 localsub(timep, 0L, &tm);
954 return &tm;
955}
956
957/*
958** gmtsub is to gmtime as localsub is to localtime.
959*/
960
961static void
962gmtsub(timep, offset, tmp)
963const time_t * const timep;
964const long offset;
965struct tm * const tmp;
966{
967 if (!gmt_is_set) {
968 gmt_is_set = TRUE;
969#ifdef ALL_STATE
970 gmtptr = (struct state *) malloc(sizeof *gmtptr);
971 if (gmtptr != NULL)
972#endif /* defined ALL_STATE */
973 gmtload(gmtptr);
974 }
975 timesub(timep, offset, gmtptr, tmp);
976#ifdef TM_ZONE
977 /*
978 ** Could get fancy here and deliver something such as
979 ** "GMT+xxxx" or "GMT-xxxx" if offset is non-zero,
980 ** but this is no time for a treasure hunt.
981 */
982 if (offset != 0)
1032 localsub(timep, 0L, &tm);
1033 return &tm;
1034}
1035
1036/*
1037** gmtsub is to gmtime as localsub is to localtime.
1038*/
1039
1040static void
1041gmtsub(timep, offset, tmp)
1042const time_t * const timep;
1043const long offset;
1044struct tm * const tmp;
1045{
1046 if (!gmt_is_set) {
1047 gmt_is_set = TRUE;
1048#ifdef ALL_STATE
1049 gmtptr = (struct state *) malloc(sizeof *gmtptr);
1050 if (gmtptr != NULL)
1051#endif /* defined ALL_STATE */
1052 gmtload(gmtptr);
1053 }
1054 timesub(timep, offset, gmtptr, tmp);
1055#ifdef TM_ZONE
1056 /*
1057 ** Could get fancy here and deliver something such as
1058 ** "GMT+xxxx" or "GMT-xxxx" if offset is non-zero,
1059 ** but this is no time for a treasure hunt.
1060 */
1061 if (offset != 0)
983 tmp->TM_ZONE = WILDABBR;
1062 tmp->TM_ZONE = wildabbr;
984 else {
985#ifdef ALL_STATE
986 if (gmtptr == NULL)
1063 else {
1064#ifdef ALL_STATE
1065 if (gmtptr == NULL)
987 tmp->TM_ZONE = GMT;
1066 tmp->TM_ZONE = gmt;
988 else tmp->TM_ZONE = gmtptr->chars;
989#endif /* defined ALL_STATE */
990#ifndef ALL_STATE
991 tmp->TM_ZONE = gmtptr->chars;
992#endif /* State Farm */
993 }
994#endif /* defined TM_ZONE */
995}
996
997struct tm *
998gmtime(timep)
999const time_t * const timep;
1000{
1067 else tmp->TM_ZONE = gmtptr->chars;
1068#endif /* defined ALL_STATE */
1069#ifndef ALL_STATE
1070 tmp->TM_ZONE = gmtptr->chars;
1071#endif /* State Farm */
1072 }
1073#endif /* defined TM_ZONE */
1074}
1075
1076struct tm *
1077gmtime(timep)
1078const time_t * const timep;
1079{
1001 static struct tm tm;
1002
1003 gmtsub(timep, 0L, &tm);
1004 return &tm;
1005}
1006
1007#ifdef STD_INSPIRED
1008
1009struct tm *
1010offtime(timep, offset)
1011const time_t * const timep;
1012const long offset;
1013{
1080 gmtsub(timep, 0L, &tm);
1081 return &tm;
1082}
1083
1084#ifdef STD_INSPIRED
1085
1086struct tm *
1087offtime(timep, offset)
1088const time_t * const timep;
1089const long offset;
1090{
1014 static struct tm tm;
1015
1016 gmtsub(timep, offset, &tm);
1017 return &tm;
1018}
1019
1020#endif /* defined STD_INSPIRED */
1021
1022static void
1023timesub(timep, offset, sp, tmp)
1024const time_t * const timep;
1025const long offset;
1026register const struct state * const sp;
1027register struct tm * const tmp;
1028{
1029 register const struct lsinfo * lp;
1030 register long days;
1031 register long rem;
1032 register int y;
1033 register int yleap;
1034 register const int * ip;
1035 register long corr;
1036 register int hit;
1037 register int i;
1038
1039 corr = 0;
1040 hit = 0;
1041#ifdef ALL_STATE
1042 i = (sp == NULL) ? 0 : sp->leapcnt;
1043#endif /* defined ALL_STATE */
1044#ifndef ALL_STATE
1045 i = sp->leapcnt;
1046#endif /* State Farm */
1047 while (--i >= 0) {
1048 lp = &sp->lsis[i];
1049 if (*timep >= lp->ls_trans) {
1050 if (*timep == lp->ls_trans) {
1051 hit = ((i == 0 && lp->ls_corr > 0) ||
1052 lp->ls_corr > sp->lsis[i - 1].ls_corr);
1053 if (hit)
1054 while (i > 0 &&
1055 sp->lsis[i].ls_trans ==
1056 sp->lsis[i - 1].ls_trans + 1 &&
1057 sp->lsis[i].ls_corr ==
1058 sp->lsis[i - 1].ls_corr + 1) {
1059 ++hit;
1060 --i;
1061 }
1062 }
1063 corr = lp->ls_corr;
1064 break;
1065 }
1066 }
1067 days = *timep / SECSPERDAY;
1068 rem = *timep % SECSPERDAY;
1069#ifdef mc68k
1070 if (*timep == 0x80000000) {
1071 /*
1072 ** A 3B1 muffs the division on the most negative number.
1073 */
1074 days = -24855;
1075 rem = -11648;
1076 }
1091 gmtsub(timep, offset, &tm);
1092 return &tm;
1093}
1094
1095#endif /* defined STD_INSPIRED */
1096
1097static void
1098timesub(timep, offset, sp, tmp)
1099const time_t * const timep;
1100const long offset;
1101register const struct state * const sp;
1102register struct tm * const tmp;
1103{
1104 register const struct lsinfo * lp;
1105 register long days;
1106 register long rem;
1107 register int y;
1108 register int yleap;
1109 register const int * ip;
1110 register long corr;
1111 register int hit;
1112 register int i;
1113
1114 corr = 0;
1115 hit = 0;
1116#ifdef ALL_STATE
1117 i = (sp == NULL) ? 0 : sp->leapcnt;
1118#endif /* defined ALL_STATE */
1119#ifndef ALL_STATE
1120 i = sp->leapcnt;
1121#endif /* State Farm */
1122 while (--i >= 0) {
1123 lp = &sp->lsis[i];
1124 if (*timep >= lp->ls_trans) {
1125 if (*timep == lp->ls_trans) {
1126 hit = ((i == 0 && lp->ls_corr > 0) ||
1127 lp->ls_corr > sp->lsis[i - 1].ls_corr);
1128 if (hit)
1129 while (i > 0 &&
1130 sp->lsis[i].ls_trans ==
1131 sp->lsis[i - 1].ls_trans + 1 &&
1132 sp->lsis[i].ls_corr ==
1133 sp->lsis[i - 1].ls_corr + 1) {
1134 ++hit;
1135 --i;
1136 }
1137 }
1138 corr = lp->ls_corr;
1139 break;
1140 }
1141 }
1142 days = *timep / SECSPERDAY;
1143 rem = *timep % SECSPERDAY;
1144#ifdef mc68k
1145 if (*timep == 0x80000000) {
1146 /*
1147 ** A 3B1 muffs the division on the most negative number.
1148 */
1149 days = -24855;
1150 rem = -11648;
1151 }
1077#endif /* mc68k */
1152#endif /* defined mc68k */
1078 rem += (offset - corr);
1079 while (rem < 0) {
1080 rem += SECSPERDAY;
1081 --days;
1082 }
1083 while (rem >= SECSPERDAY) {
1084 rem -= SECSPERDAY;
1085 ++days;
1086 }
1087 tmp->tm_hour = (int) (rem / SECSPERHOUR);
1088 rem = rem % SECSPERHOUR;
1089 tmp->tm_min = (int) (rem / SECSPERMIN);
1090 tmp->tm_sec = (int) (rem % SECSPERMIN);
1091 if (hit)
1092 /*
1093 ** A positive leap second requires a special
1094 ** representation. This uses "... ??:59:60" et seq.
1095 */
1096 tmp->tm_sec += hit;
1097 tmp->tm_wday = (int) ((EPOCH_WDAY + days) % DAYSPERWEEK);
1098 if (tmp->tm_wday < 0)
1099 tmp->tm_wday += DAYSPERWEEK;
1100 y = EPOCH_YEAR;
1101 if (days >= 0)
1102 for ( ; ; ) {
1103 yleap = isleap(y);
1104 if (days < (long) year_lengths[yleap])
1105 break;
1106 ++y;
1107 days = days - (long) year_lengths[yleap];
1108 }
1109 else do {
1110 --y;
1111 yleap = isleap(y);
1112 days = days + (long) year_lengths[yleap];
1113 } while (days < 0);
1114 tmp->tm_year = y - TM_YEAR_BASE;
1115 tmp->tm_yday = (int) days;
1116 ip = mon_lengths[yleap];
1117 for (tmp->tm_mon = 0; days >= (long) ip[tmp->tm_mon]; ++(tmp->tm_mon))
1118 days = days - (long) ip[tmp->tm_mon];
1119 tmp->tm_mday = (int) (days + 1);
1120 tmp->tm_isdst = 0;
1121#ifdef TM_GMTOFF
1122 tmp->TM_GMTOFF = offset;
1123#endif /* defined TM_GMTOFF */
1124}
1125
1126char *
1127ctime(timep)
1128const time_t * const timep;
1129{
1153 rem += (offset - corr);
1154 while (rem < 0) {
1155 rem += SECSPERDAY;
1156 --days;
1157 }
1158 while (rem >= SECSPERDAY) {
1159 rem -= SECSPERDAY;
1160 ++days;
1161 }
1162 tmp->tm_hour = (int) (rem / SECSPERHOUR);
1163 rem = rem % SECSPERHOUR;
1164 tmp->tm_min = (int) (rem / SECSPERMIN);
1165 tmp->tm_sec = (int) (rem % SECSPERMIN);
1166 if (hit)
1167 /*
1168 ** A positive leap second requires a special
1169 ** representation. This uses "... ??:59:60" et seq.
1170 */
1171 tmp->tm_sec += hit;
1172 tmp->tm_wday = (int) ((EPOCH_WDAY + days) % DAYSPERWEEK);
1173 if (tmp->tm_wday < 0)
1174 tmp->tm_wday += DAYSPERWEEK;
1175 y = EPOCH_YEAR;
1176 if (days >= 0)
1177 for ( ; ; ) {
1178 yleap = isleap(y);
1179 if (days < (long) year_lengths[yleap])
1180 break;
1181 ++y;
1182 days = days - (long) year_lengths[yleap];
1183 }
1184 else do {
1185 --y;
1186 yleap = isleap(y);
1187 days = days + (long) year_lengths[yleap];
1188 } while (days < 0);
1189 tmp->tm_year = y - TM_YEAR_BASE;
1190 tmp->tm_yday = (int) days;
1191 ip = mon_lengths[yleap];
1192 for (tmp->tm_mon = 0; days >= (long) ip[tmp->tm_mon]; ++(tmp->tm_mon))
1193 days = days - (long) ip[tmp->tm_mon];
1194 tmp->tm_mday = (int) (days + 1);
1195 tmp->tm_isdst = 0;
1196#ifdef TM_GMTOFF
1197 tmp->TM_GMTOFF = offset;
1198#endif /* defined TM_GMTOFF */
1199}
1200
1201char *
1202ctime(timep)
1203const time_t * const timep;
1204{
1205/*
1206** Section 4.12.3.2 of X3.159-1989 requires that
1207** The ctime funciton converts the calendar time pointed to by timer
1208** to local time in the form of a string. It is equivalent to
1209** asctime(localtime(timer))
1210*/
1130 return asctime(localtime(timep));
1131}
1132
1133/*
1134** Adapted from code provided by Robert Elz, who writes:
1135** The "best" way to do mktime I think is based on an idea of Bob
1136** Kridle's (so its said...) from a long time ago. (mtxinu!kridle now).
1137** It does a binary search of the time_t space. Since time_t's are
1138** just 32 bits, its a max of 32 iterations (even at 64 bits it
1139** would still be very reasonable).
1140*/
1141
1142#ifndef WRONG
1143#define WRONG (-1)
1144#endif /* !defined WRONG */
1145
1146/*
1147** Simplified normalize logic courtesy Paul Eggert (eggert@twinsun.com).
1148*/
1149
1150static int
1151increment_overflow(number, delta)
1152int * number;
1153int delta;
1154{
1211 return asctime(localtime(timep));
1212}
1213
1214/*
1215** Adapted from code provided by Robert Elz, who writes:
1216** The "best" way to do mktime I think is based on an idea of Bob
1217** Kridle's (so its said...) from a long time ago. (mtxinu!kridle now).
1218** It does a binary search of the time_t space. Since time_t's are
1219** just 32 bits, its a max of 32 iterations (even at 64 bits it
1220** would still be very reasonable).
1221*/
1222
1223#ifndef WRONG
1224#define WRONG (-1)
1225#endif /* !defined WRONG */
1226
1227/*
1228** Simplified normalize logic courtesy Paul Eggert (eggert@twinsun.com).
1229*/
1230
1231static int
1232increment_overflow(number, delta)
1233int * number;
1234int delta;
1235{
1155 int number0;
1236 int number0;
1156
1157 number0 = *number;
1158 *number += delta;
1159 return (*number < number0) != (delta < 0);
1160}
1161
1162static int
1163normalize_overflow(tensptr, unitsptr, base)
1164int * const tensptr;
1165int * const unitsptr;
1166const int base;
1167{
1168 register int tensdelta;
1169
1170 tensdelta = (*unitsptr >= 0) ?
1171 (*unitsptr / base) :
1172 (-1 - (-1 - *unitsptr) / base);
1173 *unitsptr -= tensdelta * base;
1174 return increment_overflow(tensptr, tensdelta);
1175}
1176
1177static int
1178tmcomp(atmp, btmp)
1179register const struct tm * const atmp;
1180register const struct tm * const btmp;
1181{
1182 register int result;
1183
1184 if ((result = (atmp->tm_year - btmp->tm_year)) == 0 &&
1185 (result = (atmp->tm_mon - btmp->tm_mon)) == 0 &&
1186 (result = (atmp->tm_mday - btmp->tm_mday)) == 0 &&
1187 (result = (atmp->tm_hour - btmp->tm_hour)) == 0 &&
1188 (result = (atmp->tm_min - btmp->tm_min)) == 0)
1189 result = atmp->tm_sec - btmp->tm_sec;
1190 return result;
1191}
1192
1193static time_t
1194time2(tmp, funcp, offset, okayp)
1195struct tm * const tmp;
1237
1238 number0 = *number;
1239 *number += delta;
1240 return (*number < number0) != (delta < 0);
1241}
1242
1243static int
1244normalize_overflow(tensptr, unitsptr, base)
1245int * const tensptr;
1246int * const unitsptr;
1247const int base;
1248{
1249 register int tensdelta;
1250
1251 tensdelta = (*unitsptr >= 0) ?
1252 (*unitsptr / base) :
1253 (-1 - (-1 - *unitsptr) / base);
1254 *unitsptr -= tensdelta * base;
1255 return increment_overflow(tensptr, tensdelta);
1256}
1257
1258static int
1259tmcomp(atmp, btmp)
1260register const struct tm * const atmp;
1261register const struct tm * const btmp;
1262{
1263 register int result;
1264
1265 if ((result = (atmp->tm_year - btmp->tm_year)) == 0 &&
1266 (result = (atmp->tm_mon - btmp->tm_mon)) == 0 &&
1267 (result = (atmp->tm_mday - btmp->tm_mday)) == 0 &&
1268 (result = (atmp->tm_hour - btmp->tm_hour)) == 0 &&
1269 (result = (atmp->tm_min - btmp->tm_min)) == 0)
1270 result = atmp->tm_sec - btmp->tm_sec;
1271 return result;
1272}
1273
1274static time_t
1275time2(tmp, funcp, offset, okayp)
1276struct tm * const tmp;
1196void (* const funcp)();
1277void (* const funcp) P((const time_t*, long, struct tm*));
1197const long offset;
1198int * const okayp;
1199{
1200 register const struct state * sp;
1201 register int dir;
1202 register int bits;
1203 register int i, j ;
1204 register int saved_seconds;
1205 time_t newt;
1206 time_t t;
1207 struct tm yourtm, mytm;
1208
1209 *okayp = FALSE;
1210 yourtm = *tmp;
1211 if (normalize_overflow(&yourtm.tm_hour, &yourtm.tm_min, MINSPERHOUR))
1212 return WRONG;
1213 if (normalize_overflow(&yourtm.tm_mday, &yourtm.tm_hour, HOURSPERDAY))
1214 return WRONG;
1215 if (normalize_overflow(&yourtm.tm_year, &yourtm.tm_mon, MONSPERYEAR))
1216 return WRONG;
1217 /*
1218 ** Turn yourtm.tm_year into an actual year number for now.
1219 ** It is converted back to an offset from TM_YEAR_BASE later.
1220 */
1221 if (increment_overflow(&yourtm.tm_year, TM_YEAR_BASE))
1222 return WRONG;
1223 while (yourtm.tm_mday <= 0) {
1224 if (increment_overflow(&yourtm.tm_year, -1))
1225 return WRONG;
1226 yourtm.tm_mday += year_lengths[isleap(yourtm.tm_year)];
1227 }
1228 while (yourtm.tm_mday > DAYSPERLYEAR) {
1229 yourtm.tm_mday -= year_lengths[isleap(yourtm.tm_year)];
1230 if (increment_overflow(&yourtm.tm_year, 1))
1231 return WRONG;
1232 }
1233 for ( ; ; ) {
1234 i = mon_lengths[isleap(yourtm.tm_year)][yourtm.tm_mon];
1235 if (yourtm.tm_mday <= i)
1236 break;
1237 yourtm.tm_mday -= i;
1238 if (++yourtm.tm_mon >= MONSPERYEAR) {
1239 yourtm.tm_mon = 0;
1240 if (increment_overflow(&yourtm.tm_year, 1))
1241 return WRONG;
1242 }
1243 }
1244 if (increment_overflow(&yourtm.tm_year, -TM_YEAR_BASE))
1245 return WRONG;
1246 if (yourtm.tm_year + TM_YEAR_BASE < EPOCH_YEAR) {
1247 /*
1248 ** We can't set tm_sec to 0, because that might push the
1249 ** time below the minimum representable time.
1250 ** Set tm_sec to 59 instead.
1251 ** This assumes that the minimum representable time is
1252 ** not in the same minute that a leap second was deleted from,
1253 ** which is a safer assumption than using 58 would be.
1254 */
1255 if (increment_overflow(&yourtm.tm_sec, 1 - SECSPERMIN))
1256 return WRONG;
1257 saved_seconds = yourtm.tm_sec;
1258 yourtm.tm_sec = SECSPERMIN - 1;
1259 } else {
1260 saved_seconds = yourtm.tm_sec;
1261 yourtm.tm_sec = 0;
1262 }
1263 /*
1264 ** Calculate the number of magnitude bits in a time_t
1265 ** (this works regardless of whether time_t is
1266 ** signed or unsigned, though lint complains if unsigned).
1267 */
1268 for (bits = 0, t = 1; t > 0; ++bits, t <<= 1)
1269 continue;
1270 /*
1271 ** If time_t is signed, then 0 is the median value,
1272 ** if time_t is unsigned, then 1 << bits is median.
1273 */
1274 t = (t < 0) ? 0 : ((time_t) 1 << bits);
1275 for ( ; ; ) {
1276 (*funcp)(&t, offset, &mytm);
1277 dir = tmcomp(&mytm, &yourtm);
1278 if (dir != 0) {
1279 if (bits-- < 0)
1280 return WRONG;
1281 if (bits < 0)
1282 --t;
1283 else if (dir > 0)
1284 t -= (time_t) 1 << bits;
1285 else t += (time_t) 1 << bits;
1286 continue;
1287 }
1288 if (yourtm.tm_isdst < 0 || mytm.tm_isdst == yourtm.tm_isdst)
1289 break;
1290 /*
1291 ** Right time, wrong type.
1292 ** Hunt for right time, right type.
1293 ** It's okay to guess wrong since the guess
1294 ** gets checked.
1295 */
1296 /*
1297 ** The (void *) casts are the benefit of SunOS 3.3 on Sun 2's.
1298 */
1299 sp = (const struct state *)
1300 (((void *) funcp == (void *) localsub) ?
1301 lclptr : gmtptr);
1302#ifdef ALL_STATE
1303 if (sp == NULL)
1304 return WRONG;
1305#endif /* defined ALL_STATE */
1306 for (i = 0; i < sp->typecnt; ++i) {
1307 if (sp->ttis[i].tt_isdst != yourtm.tm_isdst)
1308 continue;
1309 for (j = 0; j < sp->typecnt; ++j) {
1310 if (sp->ttis[j].tt_isdst == yourtm.tm_isdst)
1311 continue;
1312 newt = t + sp->ttis[j].tt_gmtoff -
1313 sp->ttis[i].tt_gmtoff;
1314 (*funcp)(&newt, offset, &mytm);
1315 if (tmcomp(&mytm, &yourtm) != 0)
1316 continue;
1317 if (mytm.tm_isdst != yourtm.tm_isdst)
1318 continue;
1319 /*
1320 ** We have a match.
1321 */
1322 t = newt;
1323 goto label;
1324 }
1325 }
1326 return WRONG;
1327 }
1328label:
1329 newt = t + saved_seconds;
1330 if ((newt < t) != (saved_seconds < 0))
1331 return WRONG;
1332 t = newt;
1333 (*funcp)(&t, offset, tmp);
1334 *okayp = TRUE;
1335 return t;
1336}
1337
1338static time_t
1339time1(tmp, funcp, offset)
1340struct tm * const tmp;
1278const long offset;
1279int * const okayp;
1280{
1281 register const struct state * sp;
1282 register int dir;
1283 register int bits;
1284 register int i, j ;
1285 register int saved_seconds;
1286 time_t newt;
1287 time_t t;
1288 struct tm yourtm, mytm;
1289
1290 *okayp = FALSE;
1291 yourtm = *tmp;
1292 if (normalize_overflow(&yourtm.tm_hour, &yourtm.tm_min, MINSPERHOUR))
1293 return WRONG;
1294 if (normalize_overflow(&yourtm.tm_mday, &yourtm.tm_hour, HOURSPERDAY))
1295 return WRONG;
1296 if (normalize_overflow(&yourtm.tm_year, &yourtm.tm_mon, MONSPERYEAR))
1297 return WRONG;
1298 /*
1299 ** Turn yourtm.tm_year into an actual year number for now.
1300 ** It is converted back to an offset from TM_YEAR_BASE later.
1301 */
1302 if (increment_overflow(&yourtm.tm_year, TM_YEAR_BASE))
1303 return WRONG;
1304 while (yourtm.tm_mday <= 0) {
1305 if (increment_overflow(&yourtm.tm_year, -1))
1306 return WRONG;
1307 yourtm.tm_mday += year_lengths[isleap(yourtm.tm_year)];
1308 }
1309 while (yourtm.tm_mday > DAYSPERLYEAR) {
1310 yourtm.tm_mday -= year_lengths[isleap(yourtm.tm_year)];
1311 if (increment_overflow(&yourtm.tm_year, 1))
1312 return WRONG;
1313 }
1314 for ( ; ; ) {
1315 i = mon_lengths[isleap(yourtm.tm_year)][yourtm.tm_mon];
1316 if (yourtm.tm_mday <= i)
1317 break;
1318 yourtm.tm_mday -= i;
1319 if (++yourtm.tm_mon >= MONSPERYEAR) {
1320 yourtm.tm_mon = 0;
1321 if (increment_overflow(&yourtm.tm_year, 1))
1322 return WRONG;
1323 }
1324 }
1325 if (increment_overflow(&yourtm.tm_year, -TM_YEAR_BASE))
1326 return WRONG;
1327 if (yourtm.tm_year + TM_YEAR_BASE < EPOCH_YEAR) {
1328 /*
1329 ** We can't set tm_sec to 0, because that might push the
1330 ** time below the minimum representable time.
1331 ** Set tm_sec to 59 instead.
1332 ** This assumes that the minimum representable time is
1333 ** not in the same minute that a leap second was deleted from,
1334 ** which is a safer assumption than using 58 would be.
1335 */
1336 if (increment_overflow(&yourtm.tm_sec, 1 - SECSPERMIN))
1337 return WRONG;
1338 saved_seconds = yourtm.tm_sec;
1339 yourtm.tm_sec = SECSPERMIN - 1;
1340 } else {
1341 saved_seconds = yourtm.tm_sec;
1342 yourtm.tm_sec = 0;
1343 }
1344 /*
1345 ** Calculate the number of magnitude bits in a time_t
1346 ** (this works regardless of whether time_t is
1347 ** signed or unsigned, though lint complains if unsigned).
1348 */
1349 for (bits = 0, t = 1; t > 0; ++bits, t <<= 1)
1350 continue;
1351 /*
1352 ** If time_t is signed, then 0 is the median value,
1353 ** if time_t is unsigned, then 1 << bits is median.
1354 */
1355 t = (t < 0) ? 0 : ((time_t) 1 << bits);
1356 for ( ; ; ) {
1357 (*funcp)(&t, offset, &mytm);
1358 dir = tmcomp(&mytm, &yourtm);
1359 if (dir != 0) {
1360 if (bits-- < 0)
1361 return WRONG;
1362 if (bits < 0)
1363 --t;
1364 else if (dir > 0)
1365 t -= (time_t) 1 << bits;
1366 else t += (time_t) 1 << bits;
1367 continue;
1368 }
1369 if (yourtm.tm_isdst < 0 || mytm.tm_isdst == yourtm.tm_isdst)
1370 break;
1371 /*
1372 ** Right time, wrong type.
1373 ** Hunt for right time, right type.
1374 ** It's okay to guess wrong since the guess
1375 ** gets checked.
1376 */
1377 /*
1378 ** The (void *) casts are the benefit of SunOS 3.3 on Sun 2's.
1379 */
1380 sp = (const struct state *)
1381 (((void *) funcp == (void *) localsub) ?
1382 lclptr : gmtptr);
1383#ifdef ALL_STATE
1384 if (sp == NULL)
1385 return WRONG;
1386#endif /* defined ALL_STATE */
1387 for (i = 0; i < sp->typecnt; ++i) {
1388 if (sp->ttis[i].tt_isdst != yourtm.tm_isdst)
1389 continue;
1390 for (j = 0; j < sp->typecnt; ++j) {
1391 if (sp->ttis[j].tt_isdst == yourtm.tm_isdst)
1392 continue;
1393 newt = t + sp->ttis[j].tt_gmtoff -
1394 sp->ttis[i].tt_gmtoff;
1395 (*funcp)(&newt, offset, &mytm);
1396 if (tmcomp(&mytm, &yourtm) != 0)
1397 continue;
1398 if (mytm.tm_isdst != yourtm.tm_isdst)
1399 continue;
1400 /*
1401 ** We have a match.
1402 */
1403 t = newt;
1404 goto label;
1405 }
1406 }
1407 return WRONG;
1408 }
1409label:
1410 newt = t + saved_seconds;
1411 if ((newt < t) != (saved_seconds < 0))
1412 return WRONG;
1413 t = newt;
1414 (*funcp)(&t, offset, tmp);
1415 *okayp = TRUE;
1416 return t;
1417}
1418
1419static time_t
1420time1(tmp, funcp, offset)
1421struct tm * const tmp;
1341void (* const funcp)();
1422void (* const funcp) P((const time_t*, long, struct tm*));
1342const long offset;
1343{
1344 register time_t t;
1345 register const struct state * sp;
1346 register int samei, otheri;
1347 int okay;
1348
1349 if (tmp->tm_isdst > 1)
1350 tmp->tm_isdst = 1;
1351 t = time2(tmp, funcp, offset, &okay);
1352#ifdef PCTS
1353 /*
1354 ** PCTS code courtesy Grant Sullivan (grant@osf.org).
1355 */
1356 if (okay)
1357 return t;
1358 if (tmp->tm_isdst < 0)
1359 tmp->tm_isdst = 0; /* reset to std and try again */
1360#endif /* defined PCTS */
1361#ifndef PCTS
1362 if (okay || tmp->tm_isdst < 0)
1363 return t;
1364#endif /* !defined PCTS */
1365 /*
1366 ** We're supposed to assume that somebody took a time of one type
1367 ** and did some math on it that yielded a "struct tm" that's bad.
1368 ** We try to divine the type they started from and adjust to the
1369 ** type they need.
1370 */
1371 /*
1372 ** The (void *) casts are the benefit of SunOS 3.3 on Sun 2's.
1373 */
1374 sp = (const struct state *) (((void *) funcp == (void *) localsub) ?
1375 lclptr : gmtptr);
1376#ifdef ALL_STATE
1377 if (sp == NULL)
1378 return WRONG;
1379#endif /* defined ALL_STATE */
1380 for (samei = 0; samei < sp->typecnt; ++samei) {
1381 if (sp->ttis[samei].tt_isdst != tmp->tm_isdst)
1382 continue;
1383 for (otheri = 0; otheri < sp->typecnt; ++otheri) {
1384 if (sp->ttis[otheri].tt_isdst == tmp->tm_isdst)
1385 continue;
1386 tmp->tm_sec += sp->ttis[otheri].tt_gmtoff -
1387 sp->ttis[samei].tt_gmtoff;
1388 tmp->tm_isdst = !tmp->tm_isdst;
1389 t = time2(tmp, funcp, offset, &okay);
1390 if (okay)
1391 return t;
1392 tmp->tm_sec -= sp->ttis[otheri].tt_gmtoff -
1393 sp->ttis[samei].tt_gmtoff;
1394 tmp->tm_isdst = !tmp->tm_isdst;
1395 }
1396 }
1397 return WRONG;
1398}
1399
1400time_t
1401mktime(tmp)
1402struct tm * const tmp;
1403{
1423const long offset;
1424{
1425 register time_t t;
1426 register const struct state * sp;
1427 register int samei, otheri;
1428 int okay;
1429
1430 if (tmp->tm_isdst > 1)
1431 tmp->tm_isdst = 1;
1432 t = time2(tmp, funcp, offset, &okay);
1433#ifdef PCTS
1434 /*
1435 ** PCTS code courtesy Grant Sullivan (grant@osf.org).
1436 */
1437 if (okay)
1438 return t;
1439 if (tmp->tm_isdst < 0)
1440 tmp->tm_isdst = 0; /* reset to std and try again */
1441#endif /* defined PCTS */
1442#ifndef PCTS
1443 if (okay || tmp->tm_isdst < 0)
1444 return t;
1445#endif /* !defined PCTS */
1446 /*
1447 ** We're supposed to assume that somebody took a time of one type
1448 ** and did some math on it that yielded a "struct tm" that's bad.
1449 ** We try to divine the type they started from and adjust to the
1450 ** type they need.
1451 */
1452 /*
1453 ** The (void *) casts are the benefit of SunOS 3.3 on Sun 2's.
1454 */
1455 sp = (const struct state *) (((void *) funcp == (void *) localsub) ?
1456 lclptr : gmtptr);
1457#ifdef ALL_STATE
1458 if (sp == NULL)
1459 return WRONG;
1460#endif /* defined ALL_STATE */
1461 for (samei = 0; samei < sp->typecnt; ++samei) {
1462 if (sp->ttis[samei].tt_isdst != tmp->tm_isdst)
1463 continue;
1464 for (otheri = 0; otheri < sp->typecnt; ++otheri) {
1465 if (sp->ttis[otheri].tt_isdst == tmp->tm_isdst)
1466 continue;
1467 tmp->tm_sec += sp->ttis[otheri].tt_gmtoff -
1468 sp->ttis[samei].tt_gmtoff;
1469 tmp->tm_isdst = !tmp->tm_isdst;
1470 t = time2(tmp, funcp, offset, &okay);
1471 if (okay)
1472 return t;
1473 tmp->tm_sec -= sp->ttis[otheri].tt_gmtoff -
1474 sp->ttis[samei].tt_gmtoff;
1475 tmp->tm_isdst = !tmp->tm_isdst;
1476 }
1477 }
1478 return WRONG;
1479}
1480
1481time_t
1482mktime(tmp)
1483struct tm * const tmp;
1484{
1485 tzset();
1404 return time1(tmp, localsub, 0L);
1405}
1406
1407#ifdef STD_INSPIRED
1408
1409time_t
1410timelocal(tmp)
1411struct tm * const tmp;
1412{
1413 tmp->tm_isdst = -1; /* in case it wasn't initialized */
1414 return mktime(tmp);
1415}
1416
1417time_t
1418timegm(tmp)
1419struct tm * const tmp;
1420{
1421 tmp->tm_isdst = 0;
1422 return time1(tmp, gmtsub, 0L);
1423}
1424
1425time_t
1426timeoff(tmp, offset)
1427struct tm * const tmp;
1428const long offset;
1429{
1430 tmp->tm_isdst = 0;
1431 return time1(tmp, gmtsub, offset);
1432}
1433
1434#endif /* defined STD_INSPIRED */
1435
1436#ifdef CMUCS
1437
1438/*
1439** The following is supplied for compatibility with
1440** previous versions of the CMUCS runtime library.
1441*/
1442
1443long
1444gtime(tmp)
1445struct tm * const tmp;
1446{
1447 const time_t t = mktime(tmp);
1448
1449 if (t == WRONG)
1450 return -1;
1451 return t;
1452}
1453
1454#endif /* defined CMUCS */
1455
1456/*
1457** XXX--is the below the right way to conditionalize??
1458*/
1459
1460#ifdef STD_INSPIRED
1461
1462/*
1463** IEEE Std 1003.1-1988 (POSIX) legislates that 536457599
1464** shall correspond to "Wed Dec 31 23:59:59 GMT 1986", which
1465** is not the case if we are accounting for leap seconds.
1466** So, we provide the following conversion routines for use
1467** when exchanging timestamps with POSIX conforming systems.
1468*/
1469
1470static long
1471leapcorr(timep)
1472time_t * timep;
1473{
1474 register struct state * sp;
1475 register struct lsinfo * lp;
1476 register int i;
1477
1486 return time1(tmp, localsub, 0L);
1487}
1488
1489#ifdef STD_INSPIRED
1490
1491time_t
1492timelocal(tmp)
1493struct tm * const tmp;
1494{
1495 tmp->tm_isdst = -1; /* in case it wasn't initialized */
1496 return mktime(tmp);
1497}
1498
1499time_t
1500timegm(tmp)
1501struct tm * const tmp;
1502{
1503 tmp->tm_isdst = 0;
1504 return time1(tmp, gmtsub, 0L);
1505}
1506
1507time_t
1508timeoff(tmp, offset)
1509struct tm * const tmp;
1510const long offset;
1511{
1512 tmp->tm_isdst = 0;
1513 return time1(tmp, gmtsub, offset);
1514}
1515
1516#endif /* defined STD_INSPIRED */
1517
1518#ifdef CMUCS
1519
1520/*
1521** The following is supplied for compatibility with
1522** previous versions of the CMUCS runtime library.
1523*/
1524
1525long
1526gtime(tmp)
1527struct tm * const tmp;
1528{
1529 const time_t t = mktime(tmp);
1530
1531 if (t == WRONG)
1532 return -1;
1533 return t;
1534}
1535
1536#endif /* defined CMUCS */
1537
1538/*
1539** XXX--is the below the right way to conditionalize??
1540*/
1541
1542#ifdef STD_INSPIRED
1543
1544/*
1545** IEEE Std 1003.1-1988 (POSIX) legislates that 536457599
1546** shall correspond to "Wed Dec 31 23:59:59 GMT 1986", which
1547** is not the case if we are accounting for leap seconds.
1548** So, we provide the following conversion routines for use
1549** when exchanging timestamps with POSIX conforming systems.
1550*/
1551
1552static long
1553leapcorr(timep)
1554time_t * timep;
1555{
1556 register struct state * sp;
1557 register struct lsinfo * lp;
1558 register int i;
1559
1478 if (!lcl_is_set)
1479 (void) tzset();
1480 sp = lclptr;
1481 i = sp->leapcnt;
1482 while (--i >= 0) {
1483 lp = &sp->lsis[i];
1484 if (*timep >= lp->ls_trans)
1485 return lp->ls_corr;
1486 }
1487 return 0;
1488}
1489
1490time_t
1491time2posix(t)
1492time_t t;
1493{
1560 sp = lclptr;
1561 i = sp->leapcnt;
1562 while (--i >= 0) {
1563 lp = &sp->lsis[i];
1564 if (*timep >= lp->ls_trans)
1565 return lp->ls_corr;
1566 }
1567 return 0;
1568}
1569
1570time_t
1571time2posix(t)
1572time_t t;
1573{
1574 tzset();
1494 return t - leapcorr(&t);
1495}
1496
1497time_t
1498posix2time(t)
1499time_t t;
1500{
1501 time_t x;
1502 time_t y;
1503
1575 return t - leapcorr(&t);
1576}
1577
1578time_t
1579posix2time(t)
1580time_t t;
1581{
1582 time_t x;
1583 time_t y;
1584
1585 tzset();
1504 /*
1505 ** For a positive leap second hit, the result
1506 ** is not unique. For a negative leap second
1507 ** hit, the corresponding time doesn't exist,
1508 ** so we return an adjacent second.
1509 */
1510 x = t + leapcorr(&t);
1511 y = x - leapcorr(&x);
1512 if (y < t) {
1513 do {
1514 x++;
1515 y = x - leapcorr(&x);
1516 } while (y < t);
1517 if (t != y)
1518 return x - 1;
1519 } else if (y > t) {
1520 do {
1521 --x;
1522 y = x - leapcorr(&x);
1523 } while (y > t);
1524 if (t != y)
1525 return x + 1;
1526 }
1527 return x;
1528}
1529
1530#endif /* defined STD_INSPIRED */
1586 /*
1587 ** For a positive leap second hit, the result
1588 ** is not unique. For a negative leap second
1589 ** hit, the corresponding time doesn't exist,
1590 ** so we return an adjacent second.
1591 */
1592 x = t + leapcorr(&t);
1593 y = x - leapcorr(&x);
1594 if (y < t) {
1595 do {
1596 x++;
1597 y = x - leapcorr(&x);
1598 } while (y < t);
1599 if (t != y)
1600 return x - 1;
1601 } else if (y > t) {
1602 do {
1603 --x;
1604 y = x - leapcorr(&x);
1605 } while (y > t);
1606 if (t != y)
1607 return x + 1;
1608 }
1609 return x;
1610}
1611
1612#endif /* defined STD_INSPIRED */