Deleted Added
sdiff udiff text old ( 177824 ) new ( 192625 )
full compact
1/*
2** This file is in the public domain, so clarified as of
3** 1996-06-05 by Arthur David Olson (arthur_david_olson@nih.gov).
4*/
5
6#include <sys/cdefs.h>
7#ifndef lint
8#ifndef NOID
9static char elsieid[] __unused = "@(#)localtime.c 7.78";
10#endif /* !defined NOID */
11#endif /* !defined lint */
12__FBSDID("$FreeBSD: head/lib/libc/stdtime/localtime.c 177824 2008-04-01 06:56:11Z davidxu $");
13
14/*
15** Leap second handling from Bradley White (bww@k.gp.cs.cmu.edu).
16** POSIX-style TZ environment variable handling from Guy Harris
17** (guy@auspex.com).
18*/
19
20/*LINTLIBRARY*/
21
22#include "namespace.h"
23#include <sys/types.h>
24#include <sys/stat.h>
25#include <fcntl.h>
26#include <pthread.h>
27#include "private.h"
28#include "un-namespace.h"
29
30#include "tzfile.h"
31
32#include "libc_private.h"
33
34#define _MUTEX_LOCK(x) if (__isthreaded) _pthread_mutex_lock(x)
35#define _MUTEX_UNLOCK(x) if (__isthreaded) _pthread_mutex_unlock(x)
36
37#define _RWLOCK_RDLOCK(x) \
38 do { \
39 if (__isthreaded) _pthread_rwlock_rdlock(x); \

--- 29 unchanged lines hidden (view full) ---

69** or implicitly).
70** 3. They might reference tzname[1] after setting to a time zone
71** in which Daylight Saving Time is never observed.
72** 4. They might reference tzname[0] after setting to a time zone
73** in which Standard Time is never observed.
74** 5. They might reference tm.TM_ZONE after calling offtime.
75** What's best to do in the above cases is open to debate;
76** for now, we just set things up so that in any of the five cases
77** WILDABBR is used. Another possibility: initialize tzname[0] to the
78** string "tzname[0] used before set", and similarly for the other cases.
79** And another: initialize tzname[0] to "ERA", with an explanation in the
80** manual page of what this "time zone abbreviation" means (doing this so
81** that tzname[0] has the "normal" length of three characters).
82*/
83#define WILDABBR " "
84#endif /* !defined WILDABBR */
85
86static char wildabbr[] = "WILDABBR";
87
88/*
89 * In June 2004 it was decided UTC was a more appropriate default time
90 * zone than GMT.
91 */
92
93static const char gmt[] = "UTC";
94

--- 30 unchanged lines hidden (view full) ---

125#define MY_TZNAME_MAX 255
126#endif /* !defined TZNAME_MAX */
127
128struct state {
129 int leapcnt;
130 int timecnt;
131 int typecnt;
132 int charcnt;
133 time_t ats[TZ_MAX_TIMES];
134 unsigned char types[TZ_MAX_TIMES];
135 struct ttinfo ttis[TZ_MAX_TYPES];
136 char chars[BIGGEST(BIGGEST(TZ_MAX_CHARS + 1, sizeof gmt),
137 (2 * (MY_TZNAME_MAX + 1)))];
138 struct lsinfo lsis[TZ_MAX_LEAPS];
139};
140

--- 9 unchanged lines hidden (view full) ---

150#define DAY_OF_YEAR 1 /* n - day of year */
151#define MONTH_NTH_DAY_OF_WEEK 2 /* Mm.n.d - month, week, day of week */
152
153/*
154** Prototypes for static functions.
155*/
156
157static long detzcode(const char * codep);
158static const char * getzname(const char * strp);
159static const char * getnum(const char * strp, int * nump, int min,
160 int max);
161static const char * getsecs(const char * strp, long * secsp);
162static const char * getoffset(const char * strp, long * offsetp);
163static const char * getrule(const char * strp, struct rule * rulep);
164static void gmtload(struct state * sp);
165static void gmtsub(const time_t * timep, long offset,
166 struct tm * tmp);
167static void localsub(const time_t * timep, long offset,
168 struct tm * tmp);
169static int increment_overflow(int * number, int delta);
170static int normalize_overflow(int * tensptr, int * unitsptr,
171 int base);
172static void settzname(void);
173static time_t time1(struct tm * tmp,
174 void(*funcp) (const time_t *,
175 long, struct tm *),
176 long offset);
177static time_t time2(struct tm *tmp,
178 void(*funcp) (const time_t *,
179 long, struct tm*),
180 long offset, int * okayp);
181static time_t time2sub(struct tm *tmp,
182 void(*funcp) (const time_t *,
183 long, struct tm*),
184 long offset, int * okayp, int do_norm_secs);
185static void timesub(const time_t * timep, long offset,
186 const struct state * sp, struct tm * tmp);
187static int tmcomp(const struct tm * atmp,
188 const struct tm * btmp);
189static time_t transtime(time_t janfirst, int year,
190 const struct rule * rulep, long offset);
191static int tzload(const char * name, struct state * sp);
192static int tzparse(const char * name, struct state * sp,
193 int lastditch);
194
195#ifdef ALL_STATE
196static struct state * lclptr;
197static struct state * gmtptr;
198#endif /* defined ALL_STATE */
199

--- 19 unchanged lines hidden (view full) ---

219 wildabbr
220};
221
222/*
223** Section 4.12.3 of X3.159-1989 requires that
224** Except for the strftime function, these functions [asctime,
225** ctime, gmtime, localtime] return values in one of two static
226** objects: a broken-down time structure and an array of char.
227** Thanks to Paul Eggert (eggert@twinsun.com) for noting this.
228*/
229
230static struct tm tm;
231
232#ifdef USG_COMPAT
233time_t timezone = 0;
234int daylight = 0;
235#endif /* defined USG_COMPAT */

--- 4 unchanged lines hidden (view full) ---

240
241static long
242detzcode(codep)
243const char * const codep;
244{
245 long result;
246 int i;
247
248 result = (codep[0] & 0x80) ? ~0L : 0L;
249 for (i = 0; i < 4; ++i)
250 result = (result << 8) | (codep[i] & 0xff);
251 return result;
252}
253
254static void
255settzname(void)
256{
257 struct state * sp = lclptr;
258 int i;
259
260 tzname[0] = wildabbr;
261 tzname[1] = wildabbr;

--- 32 unchanged lines hidden (view full) ---

294 for (i = 0; i < sp->timecnt; ++i) {
295 const struct ttinfo * const ttisp =
296 &sp->ttis[
297 sp->types[i]];
298
299 tzname[ttisp->tt_isdst] =
300 &sp->chars[ttisp->tt_abbrind];
301 }
302}
303
304static int
305tzload(name, sp)
306const char * name;
307struct state * const sp;
308{
309 const char * p;
310 int i;
311 int fid;
312
313 /* XXX The following is from OpenBSD, and I'm not sure it is correct */
314 if (name != NULL && issetugid() != 0)
315 if ((name[0] == ':' && name[1] == '/') ||
316 name[0] == '/' || strchr(name, '.'))
317 name = NULL;
318 if (name == NULL && (name = TZDEFAULT) == NULL)
319 return -1;

--- 31 unchanged lines hidden (view full) ---

351 return -1;
352 if ((fid = _open(name, OPEN_MODE)) == -1)
353 return -1;
354 if ((_fstat(fid, &stab) < 0) || !S_ISREG(stab.st_mode)) {
355 _close(fid);
356 return -1;
357 }
358 }
359 {
360 struct tzhead * tzhp;
361 union {
362 struct tzhead tzhead;
363 char buf[sizeof *sp + sizeof *tzhp];
364 } u;
365 int ttisstdcnt;
366 int ttisgmtcnt;
367
368 i = _read(fid, u.buf, sizeof u.buf);
369 if (_close(fid) != 0)
370 return -1;
371 ttisstdcnt = (int) detzcode(u.tzhead.tzh_ttisstdcnt);
372 ttisgmtcnt = (int) detzcode(u.tzhead.tzh_ttisgmtcnt);
373 sp->leapcnt = (int) detzcode(u.tzhead.tzh_leapcnt);
374 sp->timecnt = (int) detzcode(u.tzhead.tzh_timecnt);
375 sp->typecnt = (int) detzcode(u.tzhead.tzh_typecnt);
376 sp->charcnt = (int) detzcode(u.tzhead.tzh_charcnt);
377 p = u.tzhead.tzh_charcnt + sizeof u.tzhead.tzh_charcnt;
378 if (sp->leapcnt < 0 || sp->leapcnt > TZ_MAX_LEAPS ||
379 sp->typecnt <= 0 || sp->typecnt > TZ_MAX_TYPES ||
380 sp->timecnt < 0 || sp->timecnt > TZ_MAX_TIMES ||
381 sp->charcnt < 0 || sp->charcnt > TZ_MAX_CHARS ||
382 (ttisstdcnt != sp->typecnt && ttisstdcnt != 0) ||
383 (ttisgmtcnt != sp->typecnt && ttisgmtcnt != 0))
384 return -1;
385 if (i - (p - u.buf) < sp->timecnt * 4 + /* ats */
386 sp->timecnt + /* types */
387 sp->typecnt * (4 + 2) + /* ttinfos */
388 sp->charcnt + /* chars */
389 sp->leapcnt * (4 + 4) + /* lsinfos */
390 ttisstdcnt + /* ttisstds */
391 ttisgmtcnt) /* ttisgmts */
392 return -1;
393 for (i = 0; i < sp->timecnt; ++i) {
394 sp->ats[i] = detzcode(p);
395 p += 4;
396 }
397 for (i = 0; i < sp->timecnt; ++i) {
398 sp->types[i] = (unsigned char) *p++;
399 if (sp->types[i] >= sp->typecnt)
400 return -1;
401 }
402 for (i = 0; i < sp->typecnt; ++i) {
403 struct ttinfo * ttisp;

--- 11 unchanged lines hidden (view full) ---

415 }
416 for (i = 0; i < sp->charcnt; ++i)
417 sp->chars[i] = *p++;
418 sp->chars[i] = '\0'; /* ensure '\0' at end */
419 for (i = 0; i < sp->leapcnt; ++i) {
420 struct lsinfo * lsisp;
421
422 lsisp = &sp->lsis[i];
423 lsisp->ls_trans = detzcode(p);
424 p += 4;
425 lsisp->ls_corr = detzcode(p);
426 p += 4;
427 }
428 for (i = 0; i < sp->typecnt; ++i) {
429 struct ttinfo * ttisp;
430
431 ttisp = &sp->ttis[i];
432 if (ttisstdcnt == 0)

--- 13 unchanged lines hidden (view full) ---

446 ttisp->tt_ttisgmt = FALSE;
447 else {
448 ttisp->tt_ttisgmt = *p++;
449 if (ttisp->tt_ttisgmt != TRUE &&
450 ttisp->tt_ttisgmt != FALSE)
451 return -1;
452 }
453 }
454 }
455 return 0;
456}
457
458static const int mon_lengths[2][MONSPERYEAR] = {
459 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
460 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
461};
462
463static const int year_lengths[2] = {
464 DAYSPERNYEAR, DAYSPERLYEAR
465};
466
467/*
468** Given a pointer into a time zone string, scan until a character that is not
469** a valid character in a zone name is found. Return a pointer to that
470** character.
471*/
472
473static const char *
474getzname(strp)
475const char * strp;
476{
477 char c;
478
479 while ((c = *strp) != '\0' && !is_digit(c) && c != ',' && c != '-' &&
480 c != '+')
481 ++strp;
482 return strp;
483}
484
485/*
486** Given a pointer into a time zone string, extract a number from that string.
487** Check that the number is within a specified range; if it is not, return
488** NULL.
489** Otherwise, return a pointer to the first character not part of the number.
490*/
491
492static const char *
493getnum(strp, nump, min, max)

--- 48 unchanged lines hidden (view full) ---

542 if (*strp == ':') {
543 ++strp;
544 strp = getnum(strp, &num, 0, MINSPERHOUR - 1);
545 if (strp == NULL)
546 return NULL;
547 *secsp += num * SECSPERMIN;
548 if (*strp == ':') {
549 ++strp;
550 /* `SECSPERMIN' allows for leap seconds. */
551 strp = getnum(strp, &num, 0, SECSPERMIN);
552 if (strp == NULL)
553 return NULL;
554 *secsp += num;
555 }
556 }
557 return strp;
558}

--- 22 unchanged lines hidden (view full) ---

581 return NULL; /* illegal time */
582 if (neg)
583 *offsetp = -*offsetp;
584 return strp;
585}
586
587/*
588** Given a pointer into a time zone string, extract a rule in the form
589** date[/time]. See POSIX section 8 for the format of "date" and "time".
590** If a valid rule is not found, return NULL.
591** Otherwise, return a pointer to the first character not part of the rule.
592*/
593
594static const char *
595getrule(strp, rulep)
596const char * strp;
597struct rule * const rulep;

--- 102 unchanged lines hidden (view full) ---

700 yy1 = yy0 / 100;
701 yy2 = yy0 % 100;
702 dow = ((26 * m1 - 2) / 10 +
703 1 + yy2 + yy2 / 4 + yy1 / 4 - 2 * yy1) % 7;
704 if (dow < 0)
705 dow += DAYSPERWEEK;
706
707 /*
708 ** "dow" is the day-of-week of the first day of the month. Get
709 ** the day-of-month (zero-origin) of the first "dow" day of the
710 ** month.
711 */
712 d = rulep->r_day - dow;
713 if (d < 0)
714 d += DAYSPERWEEK;
715 for (i = 1; i < rulep->r_week; ++i) {
716 if (d + DAYSPERWEEK >=

--- 6 unchanged lines hidden (view full) ---

723 ** "d" is the day-of-month (zero-origin) of the day we want.
724 */
725 value += d * SECSPERDAY;
726 break;
727 }
728
729 /*
730 ** "value" is the Epoch-relative time of 00:00:00 UTC on the day in
731 ** question. To get the Epoch-relative time of the specified local
732 ** time on that day, add the transition time and the current offset
733 ** from UTC.
734 */
735 return value + rulep->r_time + offset;
736}
737
738/*
739** Given a POSIX section 8-style TZ string, fill in the rule tables as

--- 21 unchanged lines hidden (view full) ---

761 stdname = name;
762 if (lastditch) {
763 stdlen = strlen(name); /* length of standard zone name */
764 name += stdlen;
765 if (stdlen >= sizeof sp->chars)
766 stdlen = (sizeof sp->chars) - 1;
767 stdoffset = 0;
768 } else {
769 name = getzname(name);
770 stdlen = name - stdname;
771 if (stdlen < 3)
772 return -1;
773 if (*name == '\0')
774 return -1; /* was "stdoffset = 0;" */
775 else {
776 name = getoffset(name, &stdoffset);
777 if (name == NULL)
778 return -1;
779 }
780 }
781 load_result = tzload(TZDEFRULES, sp);
782 if (load_result != 0)
783 sp->leapcnt = 0; /* so, we're off a little */
784 if (*name != '\0') {
785 dstname = name;
786 name = getzname(name);
787 dstlen = name - dstname; /* length of DST zone name */
788 if (dstlen < 3)
789 return -1;
790 if (*name != '\0' && *name != ',' && *name != ';') {
791 name = getoffset(name, &dstoffset);
792 if (name == NULL)
793 return -1;
794 } else dstoffset = stdoffset - SECSPERHOUR;
795 if (*name == '\0' && load_result != 0)
796 name = TZDEFRULESTRING;
797 if (*name == ',' || *name == ';') {

--- 10 unchanged lines hidden (view full) ---

808 if (*name++ != ',')
809 return -1;
810 if ((name = getrule(name, &end)) == NULL)
811 return -1;
812 if (*name != '\0')
813 return -1;
814 sp->typecnt = 2; /* standard time and DST */
815 /*
816 ** Two transitions per year, from EPOCH_YEAR to 2037.
817 */
818 sp->timecnt = 2 * (2037 - EPOCH_YEAR + 1);
819 if (sp->timecnt > TZ_MAX_TIMES)
820 return -1;
821 sp->ttis[0].tt_gmtoff = -dstoffset;
822 sp->ttis[0].tt_isdst = 1;
823 sp->ttis[0].tt_abbrind = stdlen + 1;
824 sp->ttis[1].tt_gmtoff = -stdoffset;
825 sp->ttis[1].tt_isdst = 0;
826 sp->ttis[1].tt_abbrind = 0;
827 atp = sp->ats;
828 typep = sp->types;
829 janfirst = 0;
830 for (year = EPOCH_YEAR; year <= 2037; ++year) {
831 starttime = transtime(janfirst, year, &start,
832 stdoffset);
833 endtime = transtime(janfirst, year, &end,
834 dstoffset);
835 if (starttime > endtime) {
836 *atp++ = endtime;
837 *typep++ = 1; /* DST ends */
838 *atp++ = starttime;
839 *typep++ = 0; /* DST begins */
840 } else {
841 *atp++ = starttime;
842 *typep++ = 0; /* DST begins */
843 *atp++ = endtime;
844 *typep++ = 1; /* DST ends */
845 }
846 janfirst += year_lengths[isleap(year)] *
847 SECSPERDAY;
848 }
849 } else {
850 long theirstdoffset;
851 long theirdstoffset;
852 long theiroffset;
853 int isdst;
854 int i;
855 int j;

--- 98 unchanged lines hidden (view full) ---

954 }
955 return 0;
956}
957
958static void
959gmtload(sp)
960struct state * const sp;
961{
962 if (tzload(gmt, sp) != 0)
963 (void) tzparse(gmt, sp, TRUE);
964}
965
966static void
967tzsetwall_basic(int rdlocked)
968{
969 if (!rdlocked)
970 _RWLOCK_RDLOCK(&lcl_rwlock);

--- 14 unchanged lines hidden (view full) ---

985 settzname(); /* all we can do */
986 _RWLOCK_UNLOCK(&lcl_rwlock);
987 if (rdlocked)
988 _RWLOCK_RDLOCK(&lcl_rwlock);
989 return;
990 }
991 }
992#endif /* defined ALL_STATE */
993 if (tzload((char *) NULL, lclptr) != 0)
994 gmtload(lclptr);
995 settzname();
996 _RWLOCK_UNLOCK(&lcl_rwlock);
997
998 if (rdlocked)
999 _RWLOCK_RDLOCK(&lcl_rwlock);
1000}
1001

--- 46 unchanged lines hidden (view full) ---

1048 */
1049 lclptr->leapcnt = 0; /* so, we're off a little */
1050 lclptr->timecnt = 0;
1051 lclptr->typecnt = 0;
1052 lclptr->ttis[0].tt_isdst = 0;
1053 lclptr->ttis[0].tt_gmtoff = 0;
1054 lclptr->ttis[0].tt_abbrind = 0;
1055 (void) strcpy(lclptr->chars, gmt);
1056 } else if (tzload(name, lclptr) != 0)
1057 if (name[0] == ':' || tzparse(name, lclptr, FALSE) != 0)
1058 (void) gmtload(lclptr);
1059 settzname();
1060 _RWLOCK_UNLOCK(&lcl_rwlock);
1061
1062 if (rdlocked)
1063 _RWLOCK_RDLOCK(&lcl_rwlock);
1064}
1065
1066void
1067tzset(void)
1068{
1069 tzset_basic(0);
1070}
1071
1072/*
1073** The easy way to behave "as if no library function calls" localtime
1074** is to not call it--so we drop its guts into "localsub", which can be
1075** freely called. (And no, the PANS doesn't require the above behavior--
1076** but it *is* desirable.)
1077**
1078** The unused offset argument is for the benefit of mktime variants.
1079*/
1080
1081/*ARGSUSED*/
1082static void
1083localsub(timep, offset, tmp)
1084const time_t * const timep;
1085const long offset;
1086struct tm * const tmp;
1087{
1088 struct state * sp;
1089 const struct ttinfo * ttisp;
1090 int i;
1091 const time_t t = *timep;
1092
1093 sp = lclptr;
1094#ifdef ALL_STATE
1095 if (sp == NULL) {
1096 gmtsub(timep, offset, tmp);
1097 return;
1098 }
1099#endif /* defined ALL_STATE */
1100 if (sp->timecnt == 0 || t < sp->ats[0]) {
1101 i = 0;
1102 while (sp->ttis[i].tt_isdst)
1103 if (++i >= sp->typecnt) {
1104 i = 0;
1105 break;
1106 }
1107 } else {
1108 for (i = 1; i < sp->timecnt; ++i)
1109 if (t < sp->ats[i])
1110 break;
1111 i = sp->types[i - 1];
1112 }
1113 ttisp = &sp->ttis[i];
1114 /*
1115 ** To get (wrong) behavior that's compatible with System V Release 2.0
1116 ** you'd replace the statement below with
1117 ** t += ttisp->tt_gmtoff;
1118 ** timesub(&t, 0L, sp, tmp);
1119 */
1120 timesub(&t, ttisp->tt_gmtoff, sp, tmp);
1121 tmp->tm_isdst = ttisp->tt_isdst;
1122 tzname[tmp->tm_isdst] = &sp->chars[ttisp->tt_abbrind];
1123#ifdef TM_ZONE
1124 tmp->TM_ZONE = &sp->chars[ttisp->tt_abbrind];
1125#endif /* defined TM_ZONE */
1126}
1127
1128struct tm *
1129localtime(timep)
1130const time_t * const timep;
1131{
1132 static pthread_mutex_t localtime_mutex = PTHREAD_MUTEX_INITIALIZER;
1133 static pthread_key_t localtime_key = -1;

--- 29 unchanged lines hidden (view full) ---

1163 }
1164}
1165
1166/*
1167** Re-entrant version of localtime.
1168*/
1169
1170struct tm *
1171localtime_r(timep, tm)
1172const time_t * const timep;
1173struct tm * tm;
1174{
1175 _RWLOCK_RDLOCK(&lcl_rwlock);
1176 tzset_basic(1);
1177 localsub(timep, 0L, tm);
1178 _RWLOCK_UNLOCK(&lcl_rwlock);
1179 return tm;
1180}
1181
1182/*
1183** gmtsub is to gmtime as localsub is to localtime.
1184*/
1185
1186static void
1187gmtsub(timep, offset, tmp)
1188const time_t * const timep;
1189const long offset;
1190struct tm * const tmp;
1191{
1192 if (!gmt_is_set) {
1193 _MUTEX_LOCK(&gmt_mutex);
1194 if (!gmt_is_set) {
1195#ifdef ALL_STATE
1196 gmtptr = (struct state *) malloc(sizeof *gmtptr);
1197 if (gmtptr != NULL)
1198#endif /* defined ALL_STATE */
1199 gmtload(gmtptr);
1200 gmt_is_set = TRUE;
1201 }
1202 _MUTEX_UNLOCK(&gmt_mutex);
1203 }
1204 timesub(timep, offset, gmtptr, tmp);
1205#ifdef TM_ZONE
1206 /*
1207 ** Could get fancy here and deliver something such as
1208 ** "UTC+xxxx" or "UTC-xxxx" if offset is non-zero,
1209 ** but this is no time for a treasure hunt.
1210 */
1211 if (offset != 0)
1212 tmp->TM_ZONE = wildabbr;
1213 else {
1214#ifdef ALL_STATE
1215 if (gmtptr == NULL)
1216 tmp->TM_ZONE = gmt;
1217 else tmp->TM_ZONE = gmtptr->chars;
1218#endif /* defined ALL_STATE */
1219#ifndef ALL_STATE
1220 tmp->TM_ZONE = gmtptr->chars;
1221#endif /* State Farm */
1222 }
1223#endif /* defined TM_ZONE */
1224}
1225
1226struct tm *
1227gmtime(timep)
1228const time_t * const timep;
1229{
1230 static pthread_mutex_t gmtime_mutex = PTHREAD_MUTEX_INITIALIZER;
1231 static pthread_key_t gmtime_key = -1;

--- 30 unchanged lines hidden (view full) ---

1262 }
1263}
1264
1265/*
1266* Re-entrant version of gmtime.
1267*/
1268
1269struct tm *
1270gmtime_r(timep, tm)
1271const time_t * const timep;
1272struct tm * tm;
1273{
1274 gmtsub(timep, 0L, tm);
1275 return tm;
1276}
1277
1278#ifdef STD_INSPIRED
1279
1280struct tm *
1281offtime(timep, offset)
1282const time_t * const timep;
1283const long offset;
1284{
1285 gmtsub(timep, offset, &tm);
1286 return &tm;
1287}
1288
1289#endif /* defined STD_INSPIRED */
1290
1291static void
1292timesub(timep, offset, sp, tmp)
1293const time_t * const timep;
1294const long offset;
1295const struct state * const sp;
1296struct tm * const tmp;
1297{
1298 const struct lsinfo * lp;
1299 long days;
1300 long rem;
1301 long y;
1302 int yleap;
1303 const int * ip;
1304 long corr;
1305 int hit;
1306 int i;
1307
1308 corr = 0;
1309 hit = 0;
1310#ifdef ALL_STATE

--- 17 unchanged lines hidden (view full) ---

1328 ++hit;
1329 --i;
1330 }
1331 }
1332 corr = lp->ls_corr;
1333 break;
1334 }
1335 }
1336 days = *timep / SECSPERDAY;
1337 rem = *timep % SECSPERDAY;
1338#ifdef mc68k
1339 if (*timep == 0x80000000) {
1340 /*
1341 ** A 3B1 muffs the division on the most negative number.
1342 */
1343 days = -24855;
1344 rem = -11648;
1345 }
1346#endif /* defined mc68k */
1347 rem += (offset - corr);
1348 while (rem < 0) {
1349 rem += SECSPERDAY;
1350 --days;
1351 }
1352 while (rem >= SECSPERDAY) {
1353 rem -= SECSPERDAY;
1354 ++days;
1355 }
1356 tmp->tm_hour = (int) (rem / SECSPERHOUR);
1357 rem = rem % SECSPERHOUR;
1358 tmp->tm_min = (int) (rem / SECSPERMIN);
1359 /*
1360 ** A positive leap second requires a special
1361 ** representation. This uses "... ??:59:60" et seq.
1362 */
1363 tmp->tm_sec = (int) (rem % SECSPERMIN) + hit;
1364 tmp->tm_wday = (int) ((EPOCH_WDAY + days) % DAYSPERWEEK);
1365 if (tmp->tm_wday < 0)
1366 tmp->tm_wday += DAYSPERWEEK;
1367 y = EPOCH_YEAR;
1368#define LEAPS_THRU_END_OF(y) ((y) / 4 - (y) / 100 + (y) / 400)
1369 while (days < 0 || days >= (long) year_lengths[yleap = isleap(y)]) {
1370 long newy;
1371
1372 newy = y + days / DAYSPERNYEAR;
1373 if (days < 0)
1374 --newy;
1375 days -= (newy - y) * DAYSPERNYEAR +
1376 LEAPS_THRU_END_OF(newy - 1) -
1377 LEAPS_THRU_END_OF(y - 1);
1378 y = newy;
1379 }
1380 tmp->tm_year = y - TM_YEAR_BASE;
1381 tmp->tm_yday = (int) days;
1382 ip = mon_lengths[yleap];
1383 for (tmp->tm_mon = 0; days >= (long) ip[tmp->tm_mon]; ++(tmp->tm_mon))
1384 days = days - (long) ip[tmp->tm_mon];
1385 tmp->tm_mday = (int) (days + 1);
1386 tmp->tm_isdst = 0;
1387#ifdef TM_GMTOFF
1388 tmp->TM_GMTOFF = offset;
1389#endif /* defined TM_GMTOFF */
1390}
1391
1392char *
1393ctime(timep)
1394const time_t * const timep;
1395{
1396/*
1397** Section 4.12.3.2 of X3.159-1989 requires that
1398** The ctime function converts the calendar time pointed to by timer
1399** to local time in the form of a string. It is equivalent to
1400** asctime(localtime(timer))
1401*/
1402 return asctime(localtime(timep));
1403}
1404
1405char *
1406ctime_r(timep, buf)
1407const time_t * const timep;
1408char * buf;
1409{
1410 struct tm tm;
1411
1412 return asctime_r(localtime_r(timep, &tm), buf);
1413}
1414
1415/*
1416** Adapted from code provided by Robert Elz, who writes:
1417** The "best" way to do mktime I think is based on an idea of Bob
1418** Kridle's (so its said...) from a long time ago.
1419** [kridle@xinet.com as of 1996-01-16.]
1420** It does a binary search of the time_t space. Since time_t's are
1421** just 32 bits, its a max of 32 iterations (even at 64 bits it
1422** would still be very reasonable).
1423*/
1424
1425#ifndef WRONG
1426#define WRONG (-1)
1427#endif /* !defined WRONG */
1428
1429/*
1430** Simplified normalize logic courtesy Paul Eggert (eggert@twinsun.com).
1431*/
1432
1433static int
1434increment_overflow(number, delta)
1435int * number;
1436int delta;
1437{
1438 int number0;
1439
1440 number0 = *number;
1441 *number += delta;
1442 return (*number < number0) != (delta < 0);
1443}
1444
1445static int
1446normalize_overflow(tensptr, unitsptr, base)
1447int * const tensptr;
1448int * const unitsptr;
1449const int base;
1450{
1451 int tensdelta;
1452
1453 tensdelta = (*unitsptr >= 0) ?
1454 (*unitsptr / base) :
1455 (-1 - (-1 - *unitsptr) / base);
1456 *unitsptr -= tensdelta * base;
1457 return increment_overflow(tensptr, tensdelta);
1458}
1459
1460static int
1461tmcomp(atmp, btmp)
1462const struct tm * const atmp;
1463const struct tm * const btmp;
1464{
1465 int result;
1466
1467 if ((result = (atmp->tm_year - btmp->tm_year)) == 0 &&
1468 (result = (atmp->tm_mon - btmp->tm_mon)) == 0 &&
1469 (result = (atmp->tm_mday - btmp->tm_mday)) == 0 &&
1470 (result = (atmp->tm_hour - btmp->tm_hour)) == 0 &&
1471 (result = (atmp->tm_min - btmp->tm_min)) == 0)
1472 result = atmp->tm_sec - btmp->tm_sec;
1473 return result;
1474}
1475
1476static time_t
1477time2sub(tmp, funcp, offset, okayp, do_norm_secs)
1478struct tm * const tmp;
1479void (* const funcp)(const time_t*, long, struct tm*);
1480const long offset;
1481int * const okayp;
1482const int do_norm_secs;
1483{
1484 const struct state * sp;
1485 int dir;
1486 int bits;
1487 int i, j ;
1488 int saved_seconds;
1489 time_t newt;
1490 time_t t;
1491 struct tm yourtm, mytm;
1492
1493 *okayp = FALSE;
1494 yourtm = *tmp;
1495 if (do_norm_secs) {
1496 if (normalize_overflow(&yourtm.tm_min, &yourtm.tm_sec,
1497 SECSPERMIN))
1498 return WRONG;
1499 }
1500 if (normalize_overflow(&yourtm.tm_hour, &yourtm.tm_min, MINSPERHOUR))
1501 return WRONG;
1502 if (normalize_overflow(&yourtm.tm_mday, &yourtm.tm_hour, HOURSPERDAY))
1503 return WRONG;
1504 if (normalize_overflow(&yourtm.tm_year, &yourtm.tm_mon, MONSPERYEAR))
1505 return WRONG;
1506 /*
1507 ** Turn yourtm.tm_year into an actual year number for now.
1508 ** It is converted back to an offset from TM_YEAR_BASE later.
1509 */
1510 if (increment_overflow(&yourtm.tm_year, TM_YEAR_BASE))
1511 return WRONG;
1512 while (yourtm.tm_mday <= 0) {
1513 if (increment_overflow(&yourtm.tm_year, -1))
1514 return WRONG;
1515 i = yourtm.tm_year + (1 < yourtm.tm_mon);
1516 yourtm.tm_mday += year_lengths[isleap(i)];
1517 }
1518 while (yourtm.tm_mday > DAYSPERLYEAR) {
1519 i = yourtm.tm_year + (1 < yourtm.tm_mon);
1520 yourtm.tm_mday -= year_lengths[isleap(i)];
1521 if (increment_overflow(&yourtm.tm_year, 1))
1522 return WRONG;
1523 }
1524 for ( ; ; ) {
1525 i = mon_lengths[isleap(yourtm.tm_year)][yourtm.tm_mon];
1526 if (yourtm.tm_mday <= i)
1527 break;
1528 yourtm.tm_mday -= i;
1529 if (++yourtm.tm_mon >= MONSPERYEAR) {
1530 yourtm.tm_mon = 0;
1531 if (increment_overflow(&yourtm.tm_year, 1))
1532 return WRONG;
1533 }
1534 }
1535 if (increment_overflow(&yourtm.tm_year, -TM_YEAR_BASE))
1536 return WRONG;
1537 /* Don't go below 1900 for POLA */
1538 if (yourtm.tm_year < 0)
1539 return WRONG;
1540 if (yourtm.tm_sec >= 0 && yourtm.tm_sec < SECSPERMIN)
1541 saved_seconds = 0;
1542 else if (yourtm.tm_year + TM_YEAR_BASE < EPOCH_YEAR) {
1543 /*
1544 ** We can't set tm_sec to 0, because that might push the
1545 ** time below the minimum representable time.
1546 ** Set tm_sec to 59 instead.
1547 ** This assumes that the minimum representable time is
1548 ** not in the same minute that a leap second was deleted from,
1549 ** which is a safer assumption than using 58 would be.
1550 */
1551 if (increment_overflow(&yourtm.tm_sec, 1 - SECSPERMIN))
1552 return WRONG;
1553 saved_seconds = yourtm.tm_sec;
1554 yourtm.tm_sec = SECSPERMIN - 1;
1555 } else {
1556 saved_seconds = yourtm.tm_sec;
1557 yourtm.tm_sec = 0;
1558 }
1559 /*
1560 ** Divide the search space in half
1561 ** (this works whether time_t is signed or unsigned).
1562 */
1563 bits = TYPE_BIT(time_t) - 1;
1564 /*
1565 ** If we have more than this, we will overflow tm_year for tmcomp().
1566 ** We should really return an error if we cannot represent it.
1567 */
1568 if (bits > 48)
1569 bits = 48;
1570 /*
1571 ** If time_t is signed, then 0 is just above the median,
1572 ** assuming two's complement arithmetic.
1573 ** If time_t is unsigned, then (1 << bits) is just above the median.
1574 */
1575 t = TYPE_SIGNED(time_t) ? 0 : (((time_t) 1) << bits);
1576 for ( ; ; ) {
1577 (*funcp)(&t, offset, &mytm);
1578 dir = tmcomp(&mytm, &yourtm);
1579 if (dir != 0) {
1580 if (bits-- < 0)
1581 return WRONG;
1582 if (bits < 0)
1583 --t; /* may be needed if new t is minimal */
1584 else if (dir > 0)
1585 t -= ((time_t) 1) << bits;
1586 else t += ((time_t) 1) << bits;
1587 continue;
1588 }
1589 if (yourtm.tm_isdst < 0 || mytm.tm_isdst == yourtm.tm_isdst)
1590 break;
1591 /*
1592 ** Right time, wrong type.
1593 ** Hunt for right time, right type.
1594 ** It's okay to guess wrong since the guess
1595 ** gets checked.
1596 */
1597 sp = (funcp == localsub) ? lclptr : gmtptr;
1598#ifdef ALL_STATE
1599 if (sp == NULL)
1600 return WRONG;
1601#endif /* defined ALL_STATE */
1602 for (i = sp->typecnt - 1; i >= 0; --i) {
1603 if (sp->ttis[i].tt_isdst != yourtm.tm_isdst)
1604 continue;
1605 for (j = sp->typecnt - 1; j >= 0; --j) {
1606 if (sp->ttis[j].tt_isdst == yourtm.tm_isdst)
1607 continue;
1608 newt = t + sp->ttis[j].tt_gmtoff -
1609 sp->ttis[i].tt_gmtoff;
1610 (*funcp)(&newt, offset, &mytm);
1611 if (tmcomp(&mytm, &yourtm) != 0)
1612 continue;
1613 if (mytm.tm_isdst != yourtm.tm_isdst)
1614 continue;
1615 /*
1616 ** We have a match.
1617 */
1618 t = newt;
1619 goto label;
1620 }
1621 }
1622 return WRONG;
1623 }
1624label:
1625 newt = t + saved_seconds;
1626 if ((newt < t) != (saved_seconds < 0))
1627 return WRONG;
1628 t = newt;
1629 (*funcp)(&t, offset, tmp);
1630 *okayp = TRUE;
1631 return t;
1632}
1633
1634static time_t
1635time2(tmp, funcp, offset, okayp)
1636struct tm * const tmp;
1637void (* const funcp)(const time_t*, long, struct tm*);
1638const long offset;
1639int * const okayp;
1640{
1641 time_t t;
1642
1643 /*
1644 ** First try without normalization of seconds
1645 ** (in case tm_sec contains a value associated with a leap second).
1646 ** If that fails, try with normalization of seconds.
1647 */
1648 t = time2sub(tmp, funcp, offset, okayp, FALSE);
1649 return *okayp ? t : time2sub(tmp, funcp, offset, okayp, TRUE);
1650}
1651
1652static time_t
1653time1(tmp, funcp, offset)
1654struct tm * const tmp;
1655void (* const funcp)(const time_t *, long, struct tm *);
1656const long offset;
1657{
1658 time_t t;
1659 const struct state * sp;
1660 int samei, otheri;
1661 int sameind, otherind;
1662 int i;
1663 int nseen;
1664 int seen[TZ_MAX_TYPES];
1665 int types[TZ_MAX_TYPES];
1666 int okay;
1667
1668 if (tmp->tm_isdst > 1)
1669 tmp->tm_isdst = 1;
1670 t = time2(tmp, funcp, offset, &okay);
1671#ifdef PCTS
1672 /*
1673 ** PCTS code courtesy Grant Sullivan (grant@osf.org).
1674 */
1675 if (okay)
1676 return t;
1677 if (tmp->tm_isdst < 0)
1678 tmp->tm_isdst = 0; /* reset to std and try again */
1679#endif /* defined PCTS */
1680#ifndef PCTS
1681 if (okay || tmp->tm_isdst < 0)
1682 return t;
1683#endif /* !defined PCTS */
1684 /*
1685 ** We're supposed to assume that somebody took a time of one type
1686 ** and did some math on it that yielded a "struct tm" that's bad.
1687 ** We try to divine the type they started from and adjust to the
1688 ** type they need.
1689 */
1690 sp = (funcp == localsub) ? lclptr : gmtptr;
1691#ifdef ALL_STATE
1692 if (sp == NULL)
1693 return WRONG;
1694#endif /* defined ALL_STATE */
1695 for (i = 0; i < sp->typecnt; ++i)
1696 seen[i] = FALSE;
1697 nseen = 0;
1698 for (i = sp->timecnt - 1; i >= 0; --i)

--- 129 unchanged lines hidden (view full) ---

1828time_t t;
1829{
1830 time_t x;
1831 time_t y;
1832
1833 tzset();
1834 /*
1835 ** For a positive leap second hit, the result
1836 ** is not unique. For a negative leap second
1837 ** hit, the corresponding time doesn't exist,
1838 ** so we return an adjacent second.
1839 */
1840 x = t + leapcorr(&t);
1841 y = x - leapcorr(&x);
1842 if (y < t) {
1843 do {
1844 x++;

--- 16 unchanged lines hidden ---