static int differ_by_repeat(pg_time_t t1, pg_time_t t0) { if (TYPE_INTEGRAL(pg_time_t) && TYPE_BIT(pg_time_t) -TYPE_SIGNED(pg_time_t) <SECSPERREPEAT_BITS) return 0; return t1 - t0 == SECSPERREPEAT; }
static int differ_by_repeat(const time_t t1, const time_t t0) { int_fast64_t _t0 = t0; int_fast64_t _t1 = t1; if (TYPE_INTEGRAL(time_t) && TYPE_BIT(time_t) - TYPE_SIGNED(time_t) < SECSPERREPEAT_BITS) return 0; return _t1 - _t0 == SECSPERREPEAT; }
#ifdef O_BINARY #define OPEN_MODE (O_RDONLY | O_BINARY) #endif /* defined O_BINARY */ #ifndef O_BINARY #define OPEN_MODE O_RDONLY #endif /* !defined O_BINARY */ /* Complex computations to determine the min/max of time_t depending * on TYPE_BIT / TYPE_SIGNED / TYPE_INTEGRAL. * These macros cannot be used in pre-processor directives, so we * let the C compiler do the work, which makes things a bit funky. */ static const time_t TIME_T_MAX = TYPE_INTEGRAL(time_t) ? ( TYPE_SIGNED(time_t) ? ~((time_t)1 << (TYPE_BIT(time_t)-1)) : ~(time_t)0 ) : /* if time_t is a floating point number */ ( sizeof(time_t) > sizeof(float) ? (time_t)DBL_MAX : (time_t)FLT_MAX ); static const time_t TIME_T_MIN = TYPE_INTEGRAL(time_t) ? ( TYPE_SIGNED(time_t) ? ((time_t)1 << (TYPE_BIT(time_t)-1)) : 0 ) : ( sizeof(time_t) > sizeof(float) ? (time_t)DBL_MIN : (time_t)FLT_MIN );
static time_t time2sub(struct tm * const tmp, struct tm * (* const funcp)(const time_t *, long, struct tm *), const long offset, int * const okayp, const int do_norm_secs) { const struct state * sp; int dir; int i, j; int saved_seconds; long li; time_t lo; time_t hi; long y; time_t newt; time_t t; struct tm yourtm, mytm; *okayp = FALSE; yourtm = *tmp; if (do_norm_secs) { if (normalize_overflow(&yourtm.tm_min, &yourtm.tm_sec, SECSPERMIN)) return WRONG; } if (normalize_overflow(&yourtm.tm_hour, &yourtm.tm_min, MINSPERHOUR)) return WRONG; if (normalize_overflow(&yourtm.tm_mday, &yourtm.tm_hour, HOURSPERDAY)) return WRONG; y = yourtm.tm_year; if (long_normalize_overflow(&y, &yourtm.tm_mon, MONSPERYEAR)) return WRONG; /* ** Turn y into an actual year number for now. ** It is converted back to an offset from TM_YEAR_BASE later. */ if (long_increment_overflow(&y, TM_YEAR_BASE)) return WRONG; while (yourtm.tm_mday <= 0) { if (long_increment_overflow(&y, -1)) return WRONG; li = y + (1 < yourtm.tm_mon); yourtm.tm_mday += year_lengths[isleap(li)]; } while (yourtm.tm_mday > DAYSPERLYEAR) { li = y + (1 < yourtm.tm_mon); yourtm.tm_mday -= year_lengths[isleap(li)]; if (long_increment_overflow(&y, 1)) return WRONG; } for ( ; ; ) { i = mon_lengths[isleap(y)][yourtm.tm_mon]; if (yourtm.tm_mday <= i) break; yourtm.tm_mday -= i; if (++yourtm.tm_mon >= MONSPERYEAR) { yourtm.tm_mon = 0; if (long_increment_overflow(&y, 1)) return WRONG; } } if (long_increment_overflow(&y, -TM_YEAR_BASE)) return WRONG; yourtm.tm_year = y; if (yourtm.tm_year != y) return WRONG; if (yourtm.tm_sec >= 0 && yourtm.tm_sec < SECSPERMIN) saved_seconds = 0; else if (y + TM_YEAR_BASE < EPOCH_YEAR) { /* ** We can't set tm_sec to 0, because that might push the ** time below the minimum representable time. ** Set tm_sec to 59 instead. ** This assumes that the minimum representable time is ** not in the same minute that a leap second was deleted from, ** which is a safer assumption than using 58 would be. */ if (increment_overflow(&yourtm.tm_sec, 1 - SECSPERMIN)) return WRONG; saved_seconds = yourtm.tm_sec; yourtm.tm_sec = SECSPERMIN - 1; } else { saved_seconds = yourtm.tm_sec; yourtm.tm_sec = 0; } /* ** Do a binary search (this works whatever time_t's type is). */ if (!TYPE_SIGNED(time_t)) { lo = 0; hi = lo - 1; } else if (!TYPE_INTEGRAL(time_t)) { if (sizeof(time_t) > sizeof(float)) hi = (time_t) DBL_MAX; else hi = (time_t) FLT_MAX; lo = -hi; } else { lo = 1; for (i = 0; i < (int) TYPE_BIT(time_t) - 1; ++i) lo *= 2; hi = -(lo + 1); } for ( ; ; ) { t = lo / 2 + hi / 2; if (t < lo) t = lo; else if (t > hi) t = hi; if ((*funcp)(&t, offset, &mytm) == NULL) { /* ** Assume that t is too extreme to be represented in ** a struct tm; arrange things so that it is less ** extreme on the next pass. */ dir = (t > 0) ? 1 : -1; } else dir = tmcomp(&mytm, &yourtm); if (dir != 0) { if (t == lo) { ++t; if (t <= lo) return WRONG; ++lo; } else if (t == hi) { --t; if (t >= hi) return WRONG; --hi; } if (lo > hi) return WRONG; if (dir > 0) hi = t; else lo = t; continue; } if (yourtm.tm_isdst < 0 || mytm.tm_isdst == yourtm.tm_isdst) break; /* ** Right time, wrong type. ** Hunt for right time, right type. ** It's okay to guess wrong since the guess ** gets checked. */ sp = (const struct state *) ((funcp == localsub) ? lclptr : gmtptr); for (i = sp->typecnt - 1; i >= 0; --i) { if (sp->ttis[i].tt_isdst != yourtm.tm_isdst) continue; for (j = sp->typecnt - 1; j >= 0; --j) { if (sp->ttis[j].tt_isdst == yourtm.tm_isdst) continue; newt = t + sp->ttis[j].tt_gmtoff - sp->ttis[i].tt_gmtoff; if ((*funcp)(&newt, offset, &mytm) == NULL) continue; if (tmcomp(&mytm, &yourtm) != 0) continue; if (mytm.tm_isdst != yourtm.tm_isdst) continue; /* ** We have a match. */ t = newt; goto label; } } return WRONG; } label: newt = t + saved_seconds; if ((newt < t) != (saved_seconds < 0)) return WRONG; t = newt; if ((*funcp)(&t, offset, tmp)) *okayp = TRUE; return t; }