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