00001
00002
00003
00004
00005
00006 #ifndef lint
00007 #ifndef NOID
00008 static char elsieid[] = "@(#)localtime.c 7.99";
00009 #endif
00010 #endif
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "private.h"
00020 #include "tzfile.h"
00021 #include "fcntl.h"
00022 #include "float.h"
00023
00024 #ifndef TZ_ABBR_MAX_LEN
00025 #define TZ_ABBR_MAX_LEN 16
00026 #endif
00027
00028 #ifndef TZ_ABBR_CHAR_SET
00029 #define TZ_ABBR_CHAR_SET \
00030 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 :+-._"
00031 #endif
00032
00033 #ifndef TZ_ABBR_ERR_CHAR
00034 #define TZ_ABBR_ERR_CHAR '_'
00035 #endif
00036
00037
00038
00039
00040
00041 #ifdef O_BINARY
00042 #define OPEN_MODE (O_RDONLY | O_BINARY)
00043 #endif
00044 #ifndef O_BINARY
00045 #define OPEN_MODE O_RDONLY
00046 #endif
00047
00048 #ifndef WILDABBR
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068 #define WILDABBR " "
00069 #endif
00070
00071 static char wildabbr[] = WILDABBR;
00072
00073 static const char gmt[] = "GMT";
00074
00075
00076
00077
00078
00079
00080
00081
00082 #ifndef TZDEFRULESTRING
00083 #define TZDEFRULESTRING ",M4.1.0,M10.5.0"
00084 #endif
00085
00086 struct ttinfo {
00087 long tt_gmtoff;
00088 int tt_isdst;
00089 int tt_abbrind;
00090 int tt_ttisstd;
00091 int tt_ttisgmt;
00092 };
00093
00094 struct lsinfo {
00095 time_t ls_trans;
00096 long ls_corr;
00097 };
00098
00099 #define BIGGEST(a, b) (((a) > (b)) ? (a) : (b))
00100
00101 #ifdef TZNAME_MAX
00102 #define MY_TZNAME_MAX TZNAME_MAX
00103 #endif
00104 #ifndef TZNAME_MAX
00105 #define MY_TZNAME_MAX 255
00106 #endif
00107
00108 struct state {
00109 int leapcnt;
00110 int timecnt;
00111 int typecnt;
00112 int charcnt;
00113 time_t ats[TZ_MAX_TIMES];
00114 unsigned char types[TZ_MAX_TIMES];
00115 struct ttinfo ttis[TZ_MAX_TYPES];
00116 char chars[BIGGEST(BIGGEST(TZ_MAX_CHARS + 1, sizeof gmt),
00117 (2 * (MY_TZNAME_MAX + 1)))];
00118 struct lsinfo lsis[TZ_MAX_LEAPS];
00119 };
00120
00121 struct rule {
00122 int r_type;
00123 int r_day;
00124 int r_week;
00125 int r_mon;
00126 long r_time;
00127 };
00128
00129 #define JULIAN_DAY 0
00130 #define DAY_OF_YEAR 1
00131 #define MONTH_NTH_DAY_OF_WEEK 2
00132
00133
00134
00135
00136
00137 static long detzcode P((const char * codep));
00138 static const char * getzname P((const char * strp));
00139 static const char * getqzname P((const char * strp, const char delim));
00140 static const char * getnum P((const char * strp, int * nump, int min,
00141 int max));
00142 static const char * getsecs P((const char * strp, long * secsp));
00143 static const char * getoffset P((const char * strp, long * offsetp));
00144 static const char * getrule P((const char * strp, struct rule * rulep));
00145 static void gmtload P((struct state * sp));
00146 static struct tm * gmtsub P((const time_t * timep, long offset,
00147 struct tm * tmp));
00148 static struct tm * localsub P((const time_t * timep, long offset,
00149 struct tm * tmp));
00150 static int increment_overflow P((int * number, int delta));
00151 static int leaps_thru_end_of P((int y));
00152 static int long_increment_overflow P((long * number, int delta));
00153 static int long_normalize_overflow P((long * tensptr,
00154 int * unitsptr, int base));
00155 static int normalize_overflow P((int * tensptr, int * unitsptr,
00156 int base));
00157 static void settzname P((void));
00158 static time_t time1 P((struct tm * tmp,
00159 struct tm * (*funcp) P((const time_t *,
00160 long, struct tm *)),
00161 long offset));
00162 static time_t time2 P((struct tm *tmp,
00163 struct tm * (*funcp) P((const time_t *,
00164 long, struct tm*)),
00165 long offset, int * okayp));
00166 static time_t time2sub P((struct tm *tmp,
00167 struct tm * (*funcp) P((const time_t *,
00168 long, struct tm*)),
00169 long offset, int * okayp, int do_norm_secs));
00170 static struct tm * timesub P((const time_t * timep, long offset,
00171 const struct state * sp, struct tm * tmp));
00172 static int tmcomp P((const struct tm * atmp,
00173 const struct tm * btmp));
00174 static time_t transtime P((time_t janfirst, int year,
00175 const struct rule * rulep, long offset));
00176 static int tzload P((const char * name, struct state * sp));
00177 static int tzparse P((const char * name, struct state * sp,
00178 int lastditch));
00179
00180 #ifdef ALL_STATE
00181 static struct state * lclptr;
00182 static struct state * gmtptr;
00183 #endif
00184
00185 #ifndef ALL_STATE
00186 static struct state lclmem;
00187 static struct state gmtmem;
00188 #define lclptr (&lclmem)
00189 #define gmtptr (&gmtmem)
00190 #endif
00191
00192 #ifndef TZ_STRLEN_MAX
00193 #define TZ_STRLEN_MAX 255
00194 #endif
00195
00196 static char lcl_TZname[TZ_STRLEN_MAX + 1];
00197 static int lcl_is_set;
00198 static int gmt_is_set;
00199
00200 char * tzname[2] = {
00201 wildabbr,
00202 wildabbr
00203 };
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213 static struct tm tm;
00214
00215 #ifdef USG_COMPAT
00216 time_t timezone = 0;
00217 int daylight = 0;
00218 #endif
00219
00220 #ifdef ALTZONE
00221 time_t altzone = 0;
00222 #endif
00223
00224 static long
00225 detzcode(codep)
00226 const char * const codep;
00227 {
00228 register long result;
00229 register int i;
00230
00231 result = (codep[0] & 0x80) ? ~0L : 0L;
00232 for (i = 0; i < 4; ++i)
00233 result = (result << 8) | (codep[i] & 0xff);
00234 return result;
00235 }
00236
00237 static void
00238 settzname P((void))
00239 {
00240 register struct state * const sp = lclptr;
00241 register int i;
00242
00243 tzname[0] = wildabbr;
00244 tzname[1] = wildabbr;
00245 #ifdef USG_COMPAT
00246 daylight = 0;
00247 timezone = 0;
00248 #endif
00249 #ifdef ALTZONE
00250 altzone = 0;
00251 #endif
00252 #ifdef ALL_STATE
00253 if (sp == NULL) {
00254 tzname[0] = tzname[1] = gmt;
00255 return;
00256 }
00257 #endif
00258 for (i = 0; i < sp->typecnt; ++i) {
00259 register const struct ttinfo * const ttisp = &sp->ttis[i];
00260
00261 tzname[ttisp->tt_isdst] =
00262 &sp->chars[ttisp->tt_abbrind];
00263 #ifdef USG_COMPAT
00264 if (ttisp->tt_isdst)
00265 daylight = 1;
00266 if (i == 0 || !ttisp->tt_isdst)
00267 timezone = -(ttisp->tt_gmtoff);
00268 #endif
00269 #ifdef ALTZONE
00270 if (i == 0 || ttisp->tt_isdst)
00271 altzone = -(ttisp->tt_gmtoff);
00272 #endif
00273 }
00274
00275
00276
00277 for (i = 0; i < sp->timecnt; ++i) {
00278 register const struct ttinfo * const ttisp =
00279 &sp->ttis[
00280 sp->types[i]];
00281
00282 tzname[ttisp->tt_isdst] =
00283 &sp->chars[ttisp->tt_abbrind];
00284 }
00285
00286
00287
00288
00289 for (i = 0; i < sp->charcnt; ++i)
00290 if (strchr(TZ_ABBR_CHAR_SET, sp->chars[i]) == NULL)
00291 sp->chars[i] = TZ_ABBR_ERR_CHAR;
00292
00293
00294
00295 for (i = 0; i < sp->typecnt; ++i) {
00296 register const struct ttinfo * const ttisp = &sp->ttis[i];
00297 register char * cp = &sp->chars[ttisp->tt_abbrind];
00298
00299 if (strlen(cp) > TZ_ABBR_MAX_LEN &&
00300 strcmp(cp, GRANDPARENTED) != 0)
00301 *(cp + TZ_ABBR_MAX_LEN) = '\0';
00302 }
00303 }
00304
00305 static int
00306 tzload(name, sp)
00307 register const char * name;
00308 register struct state * const sp;
00309 {
00310 register const char * p;
00311 register int i;
00312 register int fid;
00313
00314 if (name == NULL && (name = TZDEFAULT) == NULL) {
00315 return -1;
00316 }
00317
00318 {
00319 register int doaccess;
00320
00321
00322
00323
00324
00325
00326
00327 char fullname[FILENAME_MAX + 1];
00328
00329 if (name[0] == ':')
00330 ++name;
00331 doaccess = name[0] == '/';
00332 if (!doaccess) {
00333 if ((p = TZDIR) == NULL)
00334 return -1;
00335 if ((strlen(p) + strlen(name) + 1) >= sizeof fullname)
00336 return -1;
00337 (void) strcpy(fullname, p);
00338 (void) strcat(fullname, "/");
00339 (void) strcat(fullname, name);
00340
00341
00342
00343 if (strchr(name, '.') != NULL)
00344 doaccess = TRUE;
00345 name = fullname;
00346 }
00347 if (doaccess && access(name, R_OK) != 0)
00348 return -1;
00349 if ((fid = open(name, OPEN_MODE)) == -1)
00350 return -1;
00351 }
00352 {
00353 struct tzhead * tzhp;
00354 union {
00355 struct tzhead tzhead;
00356 char buf[sizeof *sp + sizeof *tzhp];
00357 } u;
00358 int ttisstdcnt;
00359 int ttisgmtcnt;
00360
00361 i = read(fid, u.buf, sizeof u.buf);
00362 if (close(fid) != 0)
00363 return -1;
00364 ttisstdcnt = (int) detzcode(u.tzhead.tzh_ttisstdcnt);
00365 ttisgmtcnt = (int) detzcode(u.tzhead.tzh_ttisgmtcnt);
00366 sp->leapcnt = (int) detzcode(u.tzhead.tzh_leapcnt);
00367 sp->timecnt = (int) detzcode(u.tzhead.tzh_timecnt);
00368 sp->typecnt = (int) detzcode(u.tzhead.tzh_typecnt);
00369 sp->charcnt = (int) detzcode(u.tzhead.tzh_charcnt);
00370 p = u.tzhead.tzh_charcnt + sizeof u.tzhead.tzh_charcnt;
00371 if (sp->leapcnt < 0 || sp->leapcnt > TZ_MAX_LEAPS ||
00372 sp->typecnt <= 0 || sp->typecnt > TZ_MAX_TYPES ||
00373 sp->timecnt < 0 || sp->timecnt > TZ_MAX_TIMES ||
00374 sp->charcnt < 0 || sp->charcnt > TZ_MAX_CHARS ||
00375 (ttisstdcnt != sp->typecnt && ttisstdcnt != 0) ||
00376 (ttisgmtcnt != sp->typecnt && ttisgmtcnt != 0))
00377 return -1;
00378 if (i - (p - u.buf) < sp->timecnt * 4 +
00379 sp->timecnt +
00380 sp->typecnt * (4 + 2) +
00381 sp->charcnt +
00382 sp->leapcnt * (4 + 4) +
00383 ttisstdcnt +
00384 ttisgmtcnt)
00385 return -1;
00386 for (i = 0; i < sp->timecnt; ++i) {
00387 sp->ats[i] = detzcode(p);
00388 p += 4;
00389 }
00390 for (i = 0; i < sp->timecnt; ++i) {
00391 sp->types[i] = (unsigned char) *p++;
00392 if (sp->types[i] >= sp->typecnt)
00393 return -1;
00394 }
00395 for (i = 0; i < sp->typecnt; ++i) {
00396 register struct ttinfo * ttisp;
00397
00398 ttisp = &sp->ttis[i];
00399 ttisp->tt_gmtoff = detzcode(p);
00400 p += 4;
00401 ttisp->tt_isdst = (unsigned char) *p++;
00402 if (ttisp->tt_isdst != 0 && ttisp->tt_isdst != 1)
00403 return -1;
00404 ttisp->tt_abbrind = (unsigned char) *p++;
00405 if (ttisp->tt_abbrind < 0 ||
00406 ttisp->tt_abbrind > sp->charcnt)
00407 return -1;
00408 }
00409 for (i = 0; i < sp->charcnt; ++i)
00410 sp->chars[i] = *p++;
00411 sp->chars[i] = '\0';
00412 for (i = 0; i < sp->leapcnt; ++i) {
00413 register struct lsinfo * lsisp;
00414
00415 lsisp = &sp->lsis[i];
00416 lsisp->ls_trans = detzcode(p);
00417 p += 4;
00418 lsisp->ls_corr = detzcode(p);
00419 p += 4;
00420 }
00421 for (i = 0; i < sp->typecnt; ++i) {
00422 register struct ttinfo * ttisp;
00423
00424 ttisp = &sp->ttis[i];
00425 if (ttisstdcnt == 0)
00426 ttisp->tt_ttisstd = FALSE;
00427 else {
00428 ttisp->tt_ttisstd = *p++;
00429 if (ttisp->tt_ttisstd != TRUE &&
00430 ttisp->tt_ttisstd != FALSE)
00431 return -1;
00432 }
00433 }
00434 for (i = 0; i < sp->typecnt; ++i) {
00435 register struct ttinfo * ttisp;
00436
00437 ttisp = &sp->ttis[i];
00438 if (ttisgmtcnt == 0)
00439 ttisp->tt_ttisgmt = FALSE;
00440 else {
00441 ttisp->tt_ttisgmt = *p++;
00442 if (ttisp->tt_ttisgmt != TRUE &&
00443 ttisp->tt_ttisgmt != FALSE)
00444 return -1;
00445 }
00446 }
00447
00448
00449
00450
00451
00452 for (i = 0; i < sp->timecnt - 2; ++i)
00453 if (sp->ats[i] > sp->ats[i + 1]) {
00454 ++i;
00455 if (TYPE_SIGNED(time_t)) {
00456
00457
00458
00459 sp->timecnt = i;
00460 } else {
00461
00462
00463
00464 register int j;
00465
00466 for (j = 0; j + i < sp->timecnt; ++j) {
00467 sp->ats[j] = sp->ats[j + i];
00468 sp->types[j] = sp->types[j + i];
00469 }
00470 sp->timecnt = j;
00471 }
00472 break;
00473 }
00474 }
00475 return 0;
00476 }
00477
00478 static const int mon_lengths[2][MONSPERYEAR] = {
00479 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
00480 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
00481 };
00482
00483 static const int year_lengths[2] = {
00484 DAYSPERNYEAR, DAYSPERLYEAR
00485 };
00486
00487
00488
00489
00490
00491
00492
00493 static const char *
00494 getzname(strp)
00495 register const char * strp;
00496 {
00497 register char c;
00498
00499 while ((c = *strp) != '\0' && !is_digit(c) && c != ',' && c != '-' &&
00500 c != '+')
00501 ++strp;
00502 return strp;
00503 }
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514 static const char *
00515 #if __STDC__
00516 getqzname(register const char *strp, const char delim)
00517 #else
00518 getqzname(strp, delim)
00519 register const char * strp;
00520 const char delim;
00521 #endif
00522 {
00523 register char c;
00524
00525 while ((c = *strp) != '\0' && c != delim)
00526 ++strp;
00527 return strp;
00528 }
00529
00530
00531
00532
00533
00534
00535
00536
00537 static const char *
00538 getnum(strp, nump, min, max)
00539 register const char * strp;
00540 int * const nump;
00541 const int min;
00542 const int max;
00543 {
00544 register char c;
00545 register int num;
00546
00547 if (strp == NULL || !is_digit(c = *strp))
00548 return NULL;
00549 num = 0;
00550 do {
00551 num = num * 10 + (c - '0');
00552 if (num > max)
00553 return NULL;
00554 c = *++strp;
00555 } while (is_digit(c));
00556 if (num < min)
00557 return NULL;
00558 *nump = num;
00559 return strp;
00560 }
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570 static const char *
00571 getsecs(strp, secsp)
00572 register const char * strp;
00573 long * const secsp;
00574 {
00575 int num;
00576
00577
00578
00579
00580
00581
00582
00583 strp = getnum(strp, &num, 0, HOURSPERDAY * DAYSPERWEEK - 1);
00584 if (strp == NULL)
00585 return NULL;
00586 *secsp = num * (long) SECSPERHOUR;
00587 if (*strp == ':') {
00588 ++strp;
00589 strp = getnum(strp, &num, 0, MINSPERHOUR - 1);
00590 if (strp == NULL)
00591 return NULL;
00592 *secsp += num * SECSPERMIN;
00593 if (*strp == ':') {
00594 ++strp;
00595
00596 strp = getnum(strp, &num, 0, SECSPERMIN);
00597 if (strp == NULL)
00598 return NULL;
00599 *secsp += num;
00600 }
00601 }
00602 return strp;
00603 }
00604
00605
00606
00607
00608
00609
00610
00611
00612 static const char *
00613 getoffset(strp, offsetp)
00614 register const char * strp;
00615 long * const offsetp;
00616 {
00617 register int neg = 0;
00618
00619 if (*strp == '-') {
00620 neg = 1;
00621 ++strp;
00622 } else if (*strp == '+')
00623 ++strp;
00624 strp = getsecs(strp, offsetp);
00625 if (strp == NULL)
00626 return NULL;
00627 if (neg)
00628 *offsetp = -*offsetp;
00629 return strp;
00630 }
00631
00632
00633
00634
00635
00636
00637
00638
00639 static const char *
00640 getrule(strp, rulep)
00641 const char * strp;
00642 register struct rule * const rulep;
00643 {
00644 if (*strp == 'J') {
00645
00646
00647
00648 rulep->r_type = JULIAN_DAY;
00649 ++strp;
00650 strp = getnum(strp, &rulep->r_day, 1, DAYSPERNYEAR);
00651 } else if (*strp == 'M') {
00652
00653
00654
00655 rulep->r_type = MONTH_NTH_DAY_OF_WEEK;
00656 ++strp;
00657 strp = getnum(strp, &rulep->r_mon, 1, MONSPERYEAR);
00658 if (strp == NULL)
00659 return NULL;
00660 if (*strp++ != '.')
00661 return NULL;
00662 strp = getnum(strp, &rulep->r_week, 1, 5);
00663 if (strp == NULL)
00664 return NULL;
00665 if (*strp++ != '.')
00666 return NULL;
00667 strp = getnum(strp, &rulep->r_day, 0, DAYSPERWEEK - 1);
00668 } else if (is_digit(*strp)) {
00669
00670
00671
00672 rulep->r_type = DAY_OF_YEAR;
00673 strp = getnum(strp, &rulep->r_day, 0, DAYSPERLYEAR - 1);
00674 } else return NULL;
00675 if (strp == NULL)
00676 return NULL;
00677 if (*strp == '/') {
00678
00679
00680
00681 ++strp;
00682 strp = getsecs(strp, &rulep->r_time);
00683 } else rulep->r_time = 2 * SECSPERHOUR;
00684 return strp;
00685 }
00686
00687
00688
00689
00690
00691
00692
00693 static time_t
00694 transtime(janfirst, year, rulep, offset)
00695 const time_t janfirst;
00696 const int year;
00697 register const struct rule * const rulep;
00698 const long offset;
00699 {
00700 register int leapyear;
00701 register time_t value;
00702 register int i;
00703 int d, m1, yy0, yy1, yy2, dow;
00704
00705 INITIALIZE(value);
00706 leapyear = isleap(year);
00707 switch (rulep->r_type) {
00708
00709 case JULIAN_DAY:
00710
00711
00712
00713
00714
00715
00716
00717 value = janfirst + (rulep->r_day - 1) * SECSPERDAY;
00718 if (leapyear && rulep->r_day >= 60)
00719 value += SECSPERDAY;
00720 break;
00721
00722 case DAY_OF_YEAR:
00723
00724
00725
00726
00727
00728 value = janfirst + rulep->r_day * SECSPERDAY;
00729 break;
00730
00731 case MONTH_NTH_DAY_OF_WEEK:
00732
00733
00734
00735 value = janfirst;
00736 for (i = 0; i < rulep->r_mon - 1; ++i)
00737 value += mon_lengths[leapyear][i] * SECSPERDAY;
00738
00739
00740
00741
00742
00743 m1 = (rulep->r_mon + 9) % 12 + 1;
00744 yy0 = (rulep->r_mon <= 2) ? (year - 1) : year;
00745 yy1 = yy0 / 100;
00746 yy2 = yy0 % 100;
00747 dow = ((26 * m1 - 2) / 10 +
00748 1 + yy2 + yy2 / 4 + yy1 / 4 - 2 * yy1) % 7;
00749 if (dow < 0)
00750 dow += DAYSPERWEEK;
00751
00752
00753
00754
00755
00756
00757 d = rulep->r_day - dow;
00758 if (d < 0)
00759 d += DAYSPERWEEK;
00760 for (i = 1; i < rulep->r_week; ++i) {
00761 if (d + DAYSPERWEEK >=
00762 mon_lengths[leapyear][rulep->r_mon - 1])
00763 break;
00764 d += DAYSPERWEEK;
00765 }
00766
00767
00768
00769
00770 value += d * SECSPERDAY;
00771 break;
00772 }
00773
00774
00775
00776
00777
00778
00779
00780 return value + rulep->r_time + offset;
00781 }
00782
00783
00784
00785
00786
00787
00788 static int
00789 tzparse(name, sp, lastditch)
00790 const char * name;
00791 register struct state * const sp;
00792 const int lastditch;
00793 {
00794 const char * stdname;
00795 const char * dstname;
00796 size_t stdlen;
00797 size_t dstlen;
00798 long stdoffset;
00799 long dstoffset;
00800 register time_t * atp;
00801 register unsigned char * typep;
00802 register char * cp;
00803 register int load_result;
00804
00805 INITIALIZE(dstname);
00806 stdname = name;
00807 if (lastditch) {
00808 stdlen = strlen(name);
00809 name += stdlen;
00810 if (stdlen >= sizeof sp->chars)
00811 stdlen = (sizeof sp->chars) - 1;
00812 stdoffset = 0;
00813 } else {
00814 if (*name == '<') {
00815 name++;
00816 stdname = name;
00817 name = getqzname(name, '>');
00818 if (*name != '>')
00819 return (-1);
00820 stdlen = name - stdname;
00821 name++;
00822 } else {
00823 name = getzname(name);
00824 stdlen = name - stdname;
00825 }
00826 if (*name == '\0')
00827 return -1;
00828 name = getoffset(name, &stdoffset);
00829 if (name == NULL)
00830 return -1;
00831 }
00832 load_result = tzload(TZDEFRULES, sp);
00833 if (load_result != 0)
00834 sp->leapcnt = 0;
00835 if (*name != '\0') {
00836 if (*name == '<') {
00837 dstname = ++name;
00838 name = getqzname(name, '>');
00839 if (*name != '>')
00840 return -1;
00841 dstlen = name - dstname;
00842 name++;
00843 } else {
00844 dstname = name;
00845 name = getzname(name);
00846 dstlen = name - dstname;
00847 }
00848 if (*name != '\0' && *name != ',' && *name != ';') {
00849 name = getoffset(name, &dstoffset);
00850 if (name == NULL)
00851 return -1;
00852 } else dstoffset = stdoffset - SECSPERHOUR;
00853 if (*name == '\0' && load_result != 0)
00854 name = TZDEFRULESTRING;
00855 if (*name == ',' || *name == ';') {
00856 struct rule start;
00857 struct rule end;
00858 register int year;
00859 register time_t janfirst;
00860 time_t starttime;
00861 time_t endtime;
00862
00863 ++name;
00864 if ((name = getrule(name, &start)) == NULL)
00865 return -1;
00866 if (*name++ != ',')
00867 return -1;
00868 if ((name = getrule(name, &end)) == NULL)
00869 return -1;
00870 if (*name != '\0')
00871 return -1;
00872 sp->typecnt = 2;
00873
00874
00875
00876 sp->timecnt = 2 * (2037 - EPOCH_YEAR + 1);
00877 if (sp->timecnt > TZ_MAX_TIMES)
00878 return -1;
00879 sp->ttis[0].tt_gmtoff = -dstoffset;
00880 sp->ttis[0].tt_isdst = 1;
00881 sp->ttis[0].tt_abbrind = stdlen + 1;
00882 sp->ttis[1].tt_gmtoff = -stdoffset;
00883 sp->ttis[1].tt_isdst = 0;
00884 sp->ttis[1].tt_abbrind = 0;
00885 atp = sp->ats;
00886 typep = sp->types;
00887 janfirst = 0;
00888 for (year = EPOCH_YEAR; year <= 2037; ++year) {
00889 starttime = transtime(janfirst, year, &start,
00890 stdoffset);
00891 endtime = transtime(janfirst, year, &end,
00892 dstoffset);
00893 if (starttime > endtime) {
00894 *atp++ = endtime;
00895 *typep++ = 1;
00896 *atp++ = starttime;
00897 *typep++ = 0;
00898 } else {
00899 *atp++ = starttime;
00900 *typep++ = 0;
00901 *atp++ = endtime;
00902 *typep++ = 1;
00903 }
00904 janfirst += year_lengths[isleap(year)] *
00905 SECSPERDAY;
00906 }
00907 } else {
00908 register long theirstdoffset;
00909 register long theirdstoffset;
00910 register long theiroffset;
00911 register int isdst;
00912 register int i;
00913 register int j;
00914
00915 if (*name != '\0')
00916 return -1;
00917
00918
00919
00920 theirstdoffset = 0;
00921 for (i = 0; i < sp->timecnt; ++i) {
00922 j = sp->types[i];
00923 if (!sp->ttis[j].tt_isdst) {
00924 theirstdoffset =
00925 -sp->ttis[j].tt_gmtoff;
00926 break;
00927 }
00928 }
00929 theirdstoffset = 0;
00930 for (i = 0; i < sp->timecnt; ++i) {
00931 j = sp->types[i];
00932 if (sp->ttis[j].tt_isdst) {
00933 theirdstoffset =
00934 -sp->ttis[j].tt_gmtoff;
00935 break;
00936 }
00937 }
00938
00939
00940
00941 isdst = FALSE;
00942 theiroffset = theirstdoffset;
00943
00944
00945
00946
00947 for (i = 0; i < sp->timecnt; ++i) {
00948 j = sp->types[i];
00949 sp->types[i] = sp->ttis[j].tt_isdst;
00950 if (sp->ttis[j].tt_ttisgmt) {
00951
00952 } else {
00953
00954
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965
00966
00967 if (isdst && !sp->ttis[j].tt_ttisstd) {
00968 sp->ats[i] += dstoffset -
00969 theirdstoffset;
00970 } else {
00971 sp->ats[i] += stdoffset -
00972 theirstdoffset;
00973 }
00974 }
00975 theiroffset = -sp->ttis[j].tt_gmtoff;
00976 if (sp->ttis[j].tt_isdst)
00977 theirdstoffset = theiroffset;
00978 else theirstdoffset = theiroffset;
00979 }
00980
00981
00982
00983
00984 sp->ttis[0].tt_gmtoff = -stdoffset;
00985 sp->ttis[0].tt_isdst = FALSE;
00986 sp->ttis[0].tt_abbrind = 0;
00987 sp->ttis[1].tt_gmtoff = -dstoffset;
00988 sp->ttis[1].tt_isdst = TRUE;
00989 sp->ttis[1].tt_abbrind = stdlen + 1;
00990 sp->typecnt = 2;
00991 }
00992 } else {
00993 dstlen = 0;
00994 sp->typecnt = 1;
00995 sp->timecnt = 0;
00996 sp->ttis[0].tt_gmtoff = -stdoffset;
00997 sp->ttis[0].tt_isdst = 0;
00998 sp->ttis[0].tt_abbrind = 0;
00999 }
01000 sp->charcnt = stdlen + 1;
01001 if (dstlen != 0)
01002 sp->charcnt += dstlen + 1;
01003 if ((size_t) sp->charcnt > sizeof sp->chars)
01004 return -1;
01005 cp = sp->chars;
01006 (void) strncpy(cp, stdname, stdlen);
01007 cp += stdlen;
01008 *cp++ = '\0';
01009 if (dstlen != 0) {
01010 (void) strncpy(cp, dstname, dstlen);
01011 *(cp + dstlen) = '\0';
01012 }
01013 return 0;
01014 }
01015
01016 static void
01017 gmtload(sp)
01018 struct state * const sp;
01019 {
01020 if (tzload(gmt, sp) != 0)
01021 (void) tzparse(gmt, sp, TRUE);
01022 }
01023
01024 #ifndef STD_INSPIRED
01025
01026
01027
01028
01029 static
01030 #endif
01031 void
01032 tzsetwall P((void))
01033 {
01034 if (lcl_is_set < 0)
01035 return;
01036 lcl_is_set = -1;
01037
01038 #ifdef ALL_STATE
01039 if (lclptr == NULL) {
01040 lclptr = (struct state *) malloc(sizeof *lclptr);
01041 if (lclptr == NULL) {
01042 settzname();
01043 return;
01044 }
01045 }
01046 #endif
01047 if (tzload((char *) NULL, lclptr) != 0)
01048 gmtload(lclptr);
01049 settzname();
01050 }
01051
01052 void
01053 tzset P((void))
01054 {
01055 register const char * name;
01056
01057 name = getenv("TZ");
01058 if (name == NULL) {
01059 tzsetwall();
01060 return;
01061 }
01062
01063 if (lcl_is_set > 0 && strcmp(lcl_TZname, name) == 0) {
01064 return;
01065 }
01066 lcl_is_set = strlen(name) < sizeof lcl_TZname;
01067 if (lcl_is_set)
01068 (void) strcpy(lcl_TZname, name);
01069
01070 #ifdef ALL_STATE
01071 if (lclptr == NULL) {
01072 lclptr = (struct state *) malloc(sizeof *lclptr);
01073 if (lclptr == NULL) {
01074 settzname();
01075 return;
01076 }
01077 }
01078 #endif
01079 if (*name == '\0') {
01080
01081
01082
01083 lclptr->leapcnt = 0;
01084 lclptr->timecnt = 0;
01085 lclptr->typecnt = 0;
01086 lclptr->ttis[0].tt_isdst = 0;
01087 lclptr->ttis[0].tt_gmtoff = 0;
01088 lclptr->ttis[0].tt_abbrind = 0;
01089 (void) strcpy(lclptr->chars, gmt);
01090 } else if (tzload(name, lclptr) != 0)
01091 if (name[0] == ':' || tzparse(name, lclptr, FALSE) != 0)
01092 (void) gmtload(lclptr);
01093 settzname();
01094 }
01095
01096
01097
01098
01099
01100
01101
01102
01103
01104
01105
01106 static struct tm *
01107 localsub(timep, offset, tmp)
01108 const time_t * const timep;
01109 const long offset;
01110 struct tm * const tmp;
01111 {
01112 register struct state * sp;
01113 register const struct ttinfo * ttisp;
01114 register int i;
01115 register struct tm * result;
01116 const time_t t = *timep;
01117
01118 sp = lclptr;
01119 #ifdef ALL_STATE
01120 if (sp == NULL)
01121 return gmtsub(timep, offset, tmp);
01122 #endif
01123 if (sp->timecnt == 0 || t < sp->ats[0]) {
01124 i = 0;
01125 while (sp->ttis[i].tt_isdst)
01126 if (++i >= sp->typecnt) {
01127 i = 0;
01128 break;
01129 }
01130 } else {
01131 for (i = 1; i < sp->timecnt; ++i)
01132 if (t < sp->ats[i])
01133 break;
01134 i = (int) sp->types[i - 1];
01135 }
01136 ttisp = &sp->ttis[i];
01137
01138
01139
01140
01141
01142
01143 result = timesub(&t, ttisp->tt_gmtoff, sp, tmp);
01144 tmp->tm_isdst = ttisp->tt_isdst;
01145 tzname[tmp->tm_isdst] = &sp->chars[ttisp->tt_abbrind];
01146 #ifdef TM_ZONE
01147 tmp->TM_ZONE = &sp->chars[ttisp->tt_abbrind];
01148 #endif
01149 return result;
01150 }
01151
01152 struct tm *
01153 localtime(timep)
01154 const time_t * const timep;
01155 {
01156 tzset();
01157 return localsub(timep, 0L, &tm);
01158 }
01159
01160
01161
01162
01163
01164 struct tm *
01165 localtime_r(const time_t * const timep, struct tm * tmp)
01166 {
01167 return localsub(timep, 0L, tmp);
01168 }
01169
01170
01171
01172
01173
01174 static struct tm *
01175 gmtsub(timep, offset, tmp)
01176 const time_t * const timep;
01177 const long offset;
01178 struct tm * const tmp;
01179 {
01180 register struct tm * result;
01181
01182 if (!gmt_is_set) {
01183 gmt_is_set = TRUE;
01184 #ifdef ALL_STATE
01185 gmtptr = (struct state *) malloc(sizeof *gmtptr);
01186 if (gmtptr != NULL)
01187 #endif
01188 gmtload(gmtptr);
01189 }
01190 result = timesub(timep, offset, gmtptr, tmp);
01191 #ifdef TM_ZONE
01192
01193
01194
01195
01196
01197 if (offset != 0)
01198 tmp->TM_ZONE = wildabbr;
01199 else {
01200 #ifdef ALL_STATE
01201 if (gmtptr == NULL)
01202 tmp->TM_ZONE = gmt;
01203 else tmp->TM_ZONE = gmtptr->chars;
01204 #endif
01205 #ifndef ALL_STATE
01206 tmp->TM_ZONE = gmtptr->chars;
01207 #endif
01208 }
01209 #endif
01210 return result;
01211 }
01212
01213 struct tm *
01214 gmtime(timep)
01215 const time_t * const timep;
01216 {
01217 return gmtsub(timep, 0L, &tm);
01218 }
01219
01220
01221
01222
01223
01224 struct tm *
01225 gmtime_r(const time_t * const timep, struct tm * tmp)
01226 {
01227 return gmtsub(timep, 0L, tmp);
01228 }
01229
01230 #ifdef STD_INSPIRED
01231
01232 struct tm *
01233 offtime(timep, offset)
01234 const time_t * const timep;
01235 const long offset;
01236 {
01237 return gmtsub(timep, offset, &tm);
01238 }
01239
01240 #endif
01241
01242
01243
01244
01245
01246
01247 static int
01248 leaps_thru_end_of(y)
01249 register const int y;
01250 {
01251 return (y >= 0) ? (y / 4 - y / 100 + y / 400) :
01252 -(leaps_thru_end_of(-(y + 1)) + 1);
01253 }
01254
01255 static struct tm *
01256 timesub(timep, offset, sp, tmp)
01257 const time_t * const timep;
01258 const long offset;
01259 register const struct state * const sp;
01260 register struct tm * const tmp;
01261 {
01262 register const struct lsinfo * lp;
01263 register time_t tdays;
01264 register int idays;
01265 register long rem;
01266 int y;
01267 register const int * ip;
01268 register long corr;
01269 register int hit;
01270 register int i;
01271
01272 corr = 0;
01273 hit = 0;
01274 #ifdef ALL_STATE
01275 i = (sp == NULL) ? 0 : sp->leapcnt;
01276 #endif
01277 #ifndef ALL_STATE
01278 i = sp->leapcnt;
01279 #endif
01280 while (--i >= 0) {
01281 lp = &sp->lsis[i];
01282 if (*timep >= lp->ls_trans) {
01283 if (*timep == lp->ls_trans) {
01284 hit = ((i == 0 && lp->ls_corr > 0) ||
01285 lp->ls_corr > sp->lsis[i - 1].ls_corr);
01286 if (hit)
01287 while (i > 0 &&
01288 sp->lsis[i].ls_trans ==
01289 sp->lsis[i - 1].ls_trans + 1 &&
01290 sp->lsis[i].ls_corr ==
01291 sp->lsis[i - 1].ls_corr + 1) {
01292 ++hit;
01293 --i;
01294 }
01295 }
01296 corr = lp->ls_corr;
01297 break;
01298 }
01299 }
01300 y = EPOCH_YEAR;
01301 tdays = *timep / SECSPERDAY;
01302 rem = *timep - tdays * SECSPERDAY;
01303 while (tdays < 0 || tdays >= year_lengths[isleap(y)]) {
01304 int newy;
01305 register time_t tdelta;
01306 register int idelta;
01307 register int leapdays;
01308
01309 tdelta = tdays / DAYSPERLYEAR;
01310 idelta = tdelta;
01311 if (tdelta - idelta >= 1 || idelta - tdelta >= 1)
01312 return NULL;
01313 if (idelta == 0)
01314 idelta = (tdays < 0) ? -1 : 1;
01315 newy = y;
01316 if (increment_overflow(&newy, idelta))
01317 return NULL;
01318 leapdays = leaps_thru_end_of(newy - 1) -
01319 leaps_thru_end_of(y - 1);
01320 tdays -= ((time_t) newy - y) * DAYSPERNYEAR;
01321 tdays -= leapdays;
01322 y = newy;
01323 }
01324 {
01325 register long seconds;
01326
01327 seconds = tdays * SECSPERDAY + 0.5;
01328 tdays = seconds / SECSPERDAY;
01329 rem += seconds - tdays * SECSPERDAY;
01330 }
01331
01332
01333
01334 idays = tdays;
01335 rem += offset - corr;
01336 while (rem < 0) {
01337 rem += SECSPERDAY;
01338 --idays;
01339 }
01340 while (rem >= SECSPERDAY) {
01341 rem -= SECSPERDAY;
01342 ++idays;
01343 }
01344 while (idays < 0) {
01345 if (increment_overflow(&y, -1))
01346 return NULL;
01347 idays += year_lengths[isleap(y)];
01348 }
01349 while (idays >= year_lengths[isleap(y)]) {
01350 idays -= year_lengths[isleap(y)];
01351 if (increment_overflow(&y, 1))
01352 return NULL;
01353 }
01354 tmp->tm_year = y;
01355 if (increment_overflow(&tmp->tm_year, -TM_YEAR_BASE))
01356 return NULL;
01357 tmp->tm_yday = idays;
01358
01359
01360
01361 tmp->tm_wday = EPOCH_WDAY +
01362 ((y - EPOCH_YEAR) % DAYSPERWEEK) *
01363 (DAYSPERNYEAR % DAYSPERWEEK) +
01364 leaps_thru_end_of(y - 1) -
01365 leaps_thru_end_of(EPOCH_YEAR - 1) +
01366 idays;
01367 tmp->tm_wday %= DAYSPERWEEK;
01368 if (tmp->tm_wday < 0)
01369 tmp->tm_wday += DAYSPERWEEK;
01370 tmp->tm_hour = (int) (rem / SECSPERHOUR);
01371 rem %= SECSPERHOUR;
01372 tmp->tm_min = (int) (rem / SECSPERMIN);
01373
01374
01375
01376
01377 tmp->tm_sec = (int) (rem % SECSPERMIN) + hit;
01378 ip = mon_lengths[isleap(y)];
01379 for (tmp->tm_mon = 0; idays >= ip[tmp->tm_mon]; ++(tmp->tm_mon))
01380 idays -= ip[tmp->tm_mon];
01381 tmp->tm_mday = (int) (idays + 1);
01382 tmp->tm_isdst = 0;
01383 #ifdef TM_GMTOFF
01384 tmp->TM_GMTOFF = offset;
01385 #endif
01386 return tmp;
01387 }
01388
01389 char *
01390 ctime(timep)
01391 const time_t * const timep;
01392 {
01393
01394
01395
01396
01397
01398
01399 return asctime(localtime(timep));
01400 }
01401
01402 char *
01403 ctime_r(const time_t * const timep, char * buf)
01404 {
01405 struct tm mytm;
01406
01407 return asctime_r(localtime_r(timep, &mytm), buf);
01408 }
01409
01410
01411
01412
01413
01414
01415
01416
01417
01418
01419 #ifndef WRONG
01420 #define WRONG (-1)
01421 #endif
01422
01423
01424
01425
01426
01427 static int
01428 increment_overflow(number, delta)
01429 int * number;
01430 int delta;
01431 {
01432 int number0;
01433
01434 number0 = *number;
01435 *number += delta;
01436 return (*number < number0) != (delta < 0);
01437 }
01438
01439 static int
01440 long_increment_overflow(number, delta)
01441 long * number;
01442 int delta;
01443 {
01444 long number0;
01445
01446 number0 = *number;
01447 *number += delta;
01448 return (*number < number0) != (delta < 0);
01449 }
01450
01451 static int
01452 normalize_overflow(tensptr, unitsptr, base)
01453 int * const tensptr;
01454 int * const unitsptr;
01455 const int base;
01456 {
01457 register int tensdelta;
01458
01459 tensdelta = (*unitsptr >= 0) ?
01460 (*unitsptr / base) :
01461 (-1 - (-1 - *unitsptr) / base);
01462 *unitsptr -= tensdelta * base;
01463 return increment_overflow(tensptr, tensdelta);
01464 }
01465
01466 static int
01467 long_normalize_overflow(tensptr, unitsptr, base)
01468 long * const tensptr;
01469 int * const unitsptr;
01470 const int base;
01471 {
01472 register int tensdelta;
01473
01474 tensdelta = (*unitsptr >= 0) ?
01475 (*unitsptr / base) :
01476 (-1 - (-1 - *unitsptr) / base);
01477 *unitsptr -= tensdelta * base;
01478 return long_increment_overflow(tensptr, tensdelta);
01479 }
01480
01481 static int
01482 tmcomp(atmp, btmp)
01483 register const struct tm * const atmp;
01484 register const struct tm * const btmp;
01485 {
01486 register int result;
01487
01488 if ((result = (atmp->tm_year - btmp->tm_year)) == 0 &&
01489 (result = (atmp->tm_mon - btmp->tm_mon)) == 0 &&
01490 (result = (atmp->tm_mday - btmp->tm_mday)) == 0 &&
01491 (result = (atmp->tm_hour - btmp->tm_hour)) == 0 &&
01492 (result = (atmp->tm_min - btmp->tm_min)) == 0)
01493 result = atmp->tm_sec - btmp->tm_sec;
01494 return result;
01495 }
01496
01497 static time_t
01498 time2sub(tmp, funcp, offset, okayp, do_norm_secs)
01499 struct tm * const tmp;
01500 struct tm * (* const funcp) P((const time_t*, long, struct tm*));
01501 const long offset;
01502 int * const okayp;
01503 const int do_norm_secs;
01504 {
01505 register const struct state * sp;
01506 register int dir;
01507 register int i, j;
01508 register int saved_seconds;
01509 register long li;
01510 register time_t lo;
01511 register time_t hi;
01512 long y;
01513 time_t newt;
01514 time_t t;
01515 struct tm yourtm, mytm;
01516
01517 *okayp = FALSE;
01518 yourtm = *tmp;
01519 if (do_norm_secs) {
01520 if (normalize_overflow(&yourtm.tm_min, &yourtm.tm_sec,
01521 SECSPERMIN))
01522 return WRONG;
01523 }
01524 if (normalize_overflow(&yourtm.tm_hour, &yourtm.tm_min, MINSPERHOUR))
01525 return WRONG;
01526 if (normalize_overflow(&yourtm.tm_mday, &yourtm.tm_hour, HOURSPERDAY))
01527 return WRONG;
01528 y = yourtm.tm_year;
01529 if (long_normalize_overflow(&y, &yourtm.tm_mon, MONSPERYEAR))
01530 return WRONG;
01531
01532
01533
01534
01535 if (long_increment_overflow(&y, TM_YEAR_BASE))
01536 return WRONG;
01537 while (yourtm.tm_mday <= 0) {
01538 if (long_increment_overflow(&y, -1))
01539 return WRONG;
01540 li = y + (1 < yourtm.tm_mon);
01541 yourtm.tm_mday += year_lengths[isleap(li)];
01542 }
01543 while (yourtm.tm_mday > DAYSPERLYEAR) {
01544 li = y + (1 < yourtm.tm_mon);
01545 yourtm.tm_mday -= year_lengths[isleap(li)];
01546 if (long_increment_overflow(&y, 1))
01547 return WRONG;
01548 }
01549 for ( ; ; ) {
01550 i = mon_lengths[isleap(y)][yourtm.tm_mon];
01551 if (yourtm.tm_mday <= i)
01552 break;
01553 yourtm.tm_mday -= i;
01554 if (++yourtm.tm_mon >= MONSPERYEAR) {
01555 yourtm.tm_mon = 0;
01556 if (long_increment_overflow(&y, 1))
01557 return WRONG;
01558 }
01559 }
01560 if (long_increment_overflow(&y, -TM_YEAR_BASE))
01561 return WRONG;
01562 yourtm.tm_year = y;
01563 if (yourtm.tm_year != y)
01564 return WRONG;
01565 if (yourtm.tm_sec >= 0 && yourtm.tm_sec < SECSPERMIN)
01566 saved_seconds = 0;
01567 else if (y + TM_YEAR_BASE < EPOCH_YEAR) {
01568
01569
01570
01571
01572
01573
01574
01575
01576 if (increment_overflow(&yourtm.tm_sec, 1 - SECSPERMIN))
01577 return WRONG;
01578 saved_seconds = yourtm.tm_sec;
01579 yourtm.tm_sec = SECSPERMIN - 1;
01580 } else {
01581 saved_seconds = yourtm.tm_sec;
01582 yourtm.tm_sec = 0;
01583 }
01584
01585
01586
01587 if (!TYPE_SIGNED(time_t)) {
01588 lo = 0;
01589 hi = lo - 1;
01590 }
01591 #if 0
01592 else if (!TYPE_INTEGRAL(time_t)) {
01593 if (sizeof(time_t) > sizeof(float))
01594 hi = (time_t) DBL_MAX;
01595 else hi = (time_t) FLT_MAX;
01596 lo = -hi;
01597 }
01598 #endif
01599 else {
01600 lo = 1;
01601 for (i = 0; i < (int) TYPE_BIT(time_t) - 1; ++i)
01602 lo *= 2;
01603 hi = -(lo + 1);
01604 }
01605 for ( ; ; ) {
01606 t = lo / 2 + hi / 2;
01607 if (t < lo)
01608 t = lo;
01609 else if (t > hi)
01610 t = hi;
01611 if ((*funcp)(&t, offset, &mytm) == NULL) {
01612
01613
01614
01615
01616
01617 dir = (t > 0) ? 1 : -1;
01618 } else dir = tmcomp(&mytm, &yourtm);
01619 if (dir != 0) {
01620 if (t == lo) {
01621 ++t;
01622 if (t <= lo)
01623 return WRONG;
01624 ++lo;
01625 } else if (t == hi) {
01626 --t;
01627 if (t >= hi)
01628 return WRONG;
01629 --hi;
01630 }
01631 if (lo > hi)
01632 return WRONG;
01633 if (dir > 0)
01634 hi = t;
01635 else lo = t;
01636 continue;
01637 }
01638 if (yourtm.tm_isdst < 0 || mytm.tm_isdst == yourtm.tm_isdst)
01639 break;
01640
01641
01642
01643
01644
01645
01646
01647
01648
01649 sp = (const struct state *)
01650 (((void *) funcp == (void *) localsub) ?
01651 lclptr : gmtptr);
01652 #ifdef ALL_STATE
01653 if (sp == NULL)
01654 return WRONG;
01655 #endif
01656 for (i = sp->typecnt - 1; i >= 0; --i) {
01657 if (sp->ttis[i].tt_isdst != yourtm.tm_isdst)
01658 continue;
01659 for (j = sp->typecnt - 1; j >= 0; --j) {
01660 if (sp->ttis[j].tt_isdst == yourtm.tm_isdst)
01661 continue;
01662 newt = t + sp->ttis[j].tt_gmtoff -
01663 sp->ttis[i].tt_gmtoff;
01664 if ((*funcp)(&newt, offset, &mytm) == NULL)
01665 continue;
01666 if (tmcomp(&mytm, &yourtm) != 0)
01667 continue;
01668 if (mytm.tm_isdst != yourtm.tm_isdst)
01669 continue;
01670
01671
01672
01673 t = newt;
01674 goto label;
01675 }
01676 }
01677 return WRONG;
01678 }
01679 label:
01680 newt = t + saved_seconds;
01681 if ((newt < t) != (saved_seconds < 0))
01682 return WRONG;
01683 t = newt;
01684 if ((*funcp)(&t, offset, tmp))
01685 *okayp = TRUE;
01686 return t;
01687 }
01688
01689 static time_t
01690 time2(tmp, funcp, offset, okayp)
01691 struct tm * const tmp;
01692 struct tm * (* const funcp) P((const time_t*, long, struct tm*));
01693 const long offset;
01694 int * const okayp;
01695 {
01696 time_t t;
01697
01698
01699
01700
01701
01702
01703 t = time2sub(tmp, funcp, offset, okayp, FALSE);
01704 return *okayp ? t : time2sub(tmp, funcp, offset, okayp, TRUE);
01705 }
01706
01707 static time_t
01708 time1(tmp, funcp, offset)
01709 struct tm * const tmp;
01710 struct tm * (* const funcp) P((const time_t *, long, struct tm *));
01711 const long offset;
01712 {
01713 register time_t t;
01714 register const struct state * sp;
01715 register int samei, otheri;
01716 register int sameind, otherind;
01717 register int i;
01718 register int nseen;
01719 int seen[TZ_MAX_TYPES];
01720 int types[TZ_MAX_TYPES];
01721 int okay;
01722
01723 if (tmp->tm_isdst > 1)
01724 tmp->tm_isdst = 1;
01725 t = time2(tmp, funcp, offset, &okay);
01726 #ifdef PCTS
01727
01728
01729
01730 if (okay)
01731 return t;
01732 if (tmp->tm_isdst < 0)
01733 tmp->tm_isdst = 0;
01734 #endif
01735 #ifndef PCTS
01736 if (okay || tmp->tm_isdst < 0)
01737 return t;
01738 #endif
01739
01740
01741
01742
01743
01744
01745
01746
01747
01748 sp = (const struct state *) (((void *) funcp == (void *) localsub) ?
01749 lclptr : gmtptr);
01750 #ifdef ALL_STATE
01751 if (sp == NULL)
01752 return WRONG;
01753 #endif
01754 for (i = 0; i < sp->typecnt; ++i)
01755 seen[i] = FALSE;
01756 nseen = 0;
01757 for (i = sp->timecnt - 1; i >= 0; --i)
01758 if (!seen[sp->types[i]]) {
01759 seen[sp->types[i]] = TRUE;
01760 types[nseen++] = sp->types[i];
01761 }
01762 for (sameind = 0; sameind < nseen; ++sameind) {
01763 samei = types[sameind];
01764 if (sp->ttis[samei].tt_isdst != tmp->tm_isdst)
01765 continue;
01766 for (otherind = 0; otherind < nseen; ++otherind) {
01767 otheri = types[otherind];
01768 if (sp->ttis[otheri].tt_isdst == tmp->tm_isdst)
01769 continue;
01770 tmp->tm_sec += sp->ttis[otheri].tt_gmtoff -
01771 sp->ttis[samei].tt_gmtoff;
01772 tmp->tm_isdst = !tmp->tm_isdst;
01773 t = time2(tmp, funcp, offset, &okay);
01774 if (okay)
01775 return t;
01776 tmp->tm_sec -= sp->ttis[otheri].tt_gmtoff -
01777 sp->ttis[samei].tt_gmtoff;
01778 tmp->tm_isdst = !tmp->tm_isdst;
01779 }
01780 }
01781 return WRONG;
01782 }
01783
01784 time_t
01785 mktime(tmp)
01786 struct tm * const tmp;
01787 {
01788 tzset();
01789 return time1(tmp, localsub, 0L);
01790 }
01791
01792 #ifdef STD_INSPIRED
01793
01794 time_t
01795 timelocal(tmp)
01796 struct tm * const tmp;
01797 {
01798 tmp->tm_isdst = -1;
01799 return mktime(tmp);
01800 }
01801
01802 time_t
01803 timegm(tmp)
01804 struct tm * const tmp;
01805 {
01806 tmp->tm_isdst = 0;
01807 return time1(tmp, gmtsub, 0L);
01808 }
01809
01810 time_t
01811 timeoff(tmp, offset)
01812 struct tm * const tmp;
01813 const long offset;
01814 {
01815 tmp->tm_isdst = 0;
01816 return time1(tmp, gmtsub, offset);
01817 }
01818
01819 #endif
01820
01821 #ifdef CMUCS
01822
01823
01824
01825
01826
01827
01828 long
01829 gtime(tmp)
01830 struct tm * const tmp;
01831 {
01832 const time_t t = mktime(tmp);
01833
01834 if (t == WRONG)
01835 return -1;
01836 return t;
01837 }
01838
01839 #endif
01840
01841
01842
01843
01844
01845 #ifdef STD_INSPIRED
01846
01847
01848
01849
01850
01851
01852
01853
01854
01855 static long
01856 leapcorr(timep)
01857 time_t * timep;
01858 {
01859 register struct state * sp;
01860 register struct lsinfo * lp;
01861 register int i;
01862
01863 sp = lclptr;
01864 i = sp->leapcnt;
01865 while (--i >= 0) {
01866 lp = &sp->lsis[i];
01867 if (*timep >= lp->ls_trans)
01868 return lp->ls_corr;
01869 }
01870 return 0;
01871 }
01872
01873 time_t
01874 time2posix(t)
01875 time_t t;
01876 {
01877 tzset();
01878 return t - leapcorr(&t);
01879 }
01880
01881 time_t
01882 posix2time(t)
01883 time_t t;
01884 {
01885 time_t x;
01886 time_t y;
01887
01888 tzset();
01889
01890
01891
01892
01893
01894
01895 x = t + leapcorr(&t);
01896 y = x - leapcorr(&x);
01897 if (y < t) {
01898 do {
01899 x++;
01900 y = x - leapcorr(&x);
01901 } while (y < t);
01902 if (t != y)
01903 return x - 1;
01904 } else if (y > t) {
01905 do {
01906 --x;
01907 y = x - leapcorr(&x);
01908 } while (y > t);
01909 if (t != y)
01910 return x + 1;
01911 }
01912 return x;
01913 }
01914
01915 #endif