Index: fusl/src/time/__tz.c |
diff --git a/fusl/src/time/__tz.c b/fusl/src/time/__tz.c |
index 8b84b9bd12cf9091268105357c0158357d6ab82f..b4f74312a0a3724ff8094292c12041f9b5ebb130 100644 |
--- a/fusl/src/time/__tz.c |
+++ b/fusl/src/time/__tz.c |
@@ -5,16 +5,16 @@ |
#include <string.h> |
#include "libc.h" |
-long __timezone = 0; |
-int __daylight = 0; |
-char *__tzname[2] = { 0, 0 }; |
+long __timezone = 0; |
+int __daylight = 0; |
+char* __tzname[2] = {0, 0}; |
weak_alias(__timezone, timezone); |
weak_alias(__daylight, daylight); |
weak_alias(__tzname, tzname); |
-static char std_name[TZNAME_MAX+1]; |
-static char dst_name[TZNAME_MAX+1]; |
+static char std_name[TZNAME_MAX + 1]; |
+static char dst_name[TZNAME_MAX + 1]; |
const char __gmt[] = "GMT"; |
static int dst_off; |
@@ -24,317 +24,349 @@ static const unsigned char *zi, *trans, *index, *types, *abbrevs, *abbrevs_end; |
static size_t map_size; |
static char old_tz_buf[32]; |
-static char *old_tz = old_tz_buf; |
+static char* old_tz = old_tz_buf; |
static size_t old_tz_size = sizeof old_tz_buf; |
static volatile int lock[2]; |
-static int getint(const char **p) |
-{ |
- unsigned x; |
- for (x=0; **p-'0'<10U; (*p)++) x = **p-'0' + 10*x; |
- return x; |
+static int getint(const char** p) { |
+ unsigned x; |
+ for (x = 0; **p - '0' < 10U; (*p)++) |
+ x = **p - '0' + 10 * x; |
+ return x; |
} |
-static int getoff(const char **p) |
-{ |
- int neg = 0; |
- if (**p == '-') { |
- ++*p; |
- neg = 1; |
- } else if (**p == '+') { |
- ++*p; |
- } |
- int off = 3600*getint(p); |
- if (**p == ':') { |
- ++*p; |
- off += 60*getint(p); |
- if (**p == ':') { |
- ++*p; |
- off += getint(p); |
- } |
- } |
- return neg ? -off : off; |
+static int getoff(const char** p) { |
+ int neg = 0; |
+ if (**p == '-') { |
+ ++*p; |
+ neg = 1; |
+ } else if (**p == '+') { |
+ ++*p; |
+ } |
+ int off = 3600 * getint(p); |
+ if (**p == ':') { |
+ ++*p; |
+ off += 60 * getint(p); |
+ if (**p == ':') { |
+ ++*p; |
+ off += getint(p); |
+ } |
+ } |
+ return neg ? -off : off; |
} |
-static void getrule(const char **p, int rule[5]) |
-{ |
- int r = rule[0] = **p; |
- |
- if (r!='M') { |
- if (r=='J') ++*p; |
- else rule[0] = 0; |
- rule[1] = getint(p); |
- } else { |
- ++*p; rule[1] = getint(p); |
- ++*p; rule[2] = getint(p); |
- ++*p; rule[3] = getint(p); |
- } |
- |
- if (**p=='/') { |
- ++*p; |
- rule[4] = getoff(p); |
- } else { |
- rule[4] = 7200; |
- } |
+static void getrule(const char** p, int rule[5]) { |
+ int r = rule[0] = **p; |
+ |
+ if (r != 'M') { |
+ if (r == 'J') |
+ ++*p; |
+ else |
+ rule[0] = 0; |
+ rule[1] = getint(p); |
+ } else { |
+ ++*p; |
+ rule[1] = getint(p); |
+ ++*p; |
+ rule[2] = getint(p); |
+ ++*p; |
+ rule[3] = getint(p); |
+ } |
+ |
+ if (**p == '/') { |
+ ++*p; |
+ rule[4] = getoff(p); |
+ } else { |
+ rule[4] = 7200; |
+ } |
} |
-static void getname(char *d, const char **p) |
-{ |
- int i; |
- if (**p == '<') { |
- ++*p; |
- for (i=0; **p!='>' && i<TZNAME_MAX; i++) |
- d[i] = (*p)[i]; |
- ++*p; |
- } else { |
- for (i=0; ((*p)[i]|32)-'a'<26U && i<TZNAME_MAX; i++) |
- d[i] = (*p)[i]; |
- } |
- *p += i; |
- d[i] = 0; |
+static void getname(char* d, const char** p) { |
+ int i; |
+ if (**p == '<') { |
+ ++*p; |
+ for (i = 0; **p != '>' && i < TZNAME_MAX; i++) |
+ d[i] = (*p)[i]; |
+ ++*p; |
+ } else { |
+ for (i = 0; ((*p)[i] | 32) - 'a' < 26U && i < TZNAME_MAX; i++) |
+ d[i] = (*p)[i]; |
+ } |
+ *p += i; |
+ d[i] = 0; |
} |
#define VEC(...) ((const unsigned char[]){__VA_ARGS__}) |
-static uint32_t zi_read32(const unsigned char *z) |
-{ |
- return (unsigned)z[0]<<24 | z[1]<<16 | z[2]<<8 | z[3]; |
+static uint32_t zi_read32(const unsigned char* z) { |
+ return (unsigned)z[0] << 24 | z[1] << 16 | z[2] << 8 | z[3]; |
} |
-static size_t zi_dotprod(const unsigned char *z, const unsigned char *v, size_t n) |
-{ |
- size_t y; |
- uint32_t x; |
- for (y=0; n; n--, z+=4, v++) { |
- x = zi_read32(z); |
- y += x * *v; |
- } |
- return y; |
+static size_t zi_dotprod(const unsigned char* z, |
+ const unsigned char* v, |
+ size_t n) { |
+ size_t y; |
+ uint32_t x; |
+ for (y = 0; n; n--, z += 4, v++) { |
+ x = zi_read32(z); |
+ y += x * *v; |
+ } |
+ return y; |
} |
-int __munmap(void *, size_t); |
- |
-static void do_tzset() |
-{ |
- char buf[NAME_MAX+25], *pathname=buf+24; |
- const char *try, *s, *p; |
- const unsigned char *map = 0; |
- size_t i; |
- static const char search[] = |
- "/usr/share/zoneinfo/\0/share/zoneinfo/\0/etc/zoneinfo/\0"; |
- |
- s = getenv("TZ"); |
- if (!s) s = "/etc/localtime"; |
- if (!*s) s = __gmt; |
- |
- if (old_tz && !strcmp(s, old_tz)) return; |
- |
- if (zi) __munmap((void *)zi, map_size); |
- |
- /* Cache the old value of TZ to check if it has changed. Avoid |
- * free so as not to pull it into static programs. Growth |
- * strategy makes it so free would have minimal benefit anyway. */ |
- i = strlen(s); |
- if (i > PATH_MAX+1) s = __gmt, i = 3; |
- if (i >= old_tz_size) { |
- old_tz_size *= 2; |
- if (i >= old_tz_size) old_tz_size = i+1; |
- if (old_tz_size > PATH_MAX+2) old_tz_size = PATH_MAX+2; |
- old_tz = malloc(old_tz_size); |
- } |
- if (old_tz) memcpy(old_tz, s, i+1); |
- |
- /* Non-suid can use an absolute tzfile pathname or a relative |
- * pathame beginning with "."; in secure mode, only the |
- * standard path will be searched. */ |
- if (*s == ':' || ((p=strchr(s, '/')) && !memchr(s, ',', p-s))) { |
- if (*s == ':') s++; |
- if (*s == '/' || *s == '.') { |
- if (!libc.secure || !strcmp(s, "/etc/localtime")) |
- map = __map_file(s, &map_size); |
- } else { |
- size_t l = strlen(s); |
- if (l <= NAME_MAX && !strchr(s, '.')) { |
- memcpy(pathname, s, l+1); |
- pathname[l] = 0; |
- for (try=search; !map && *try; try+=l+1) { |
- l = strlen(try); |
- memcpy(pathname-l, try, l); |
- map = __map_file(pathname-l, &map_size); |
- } |
- } |
- } |
- if (!map) s = __gmt; |
- } |
- if (map && (map_size < 44 || memcmp(map, "TZif", 4))) { |
- __munmap((void *)map, map_size); |
- map = 0; |
- s = __gmt; |
- } |
- |
- zi = map; |
- if (map) { |
- int scale = 2; |
- if (sizeof(time_t) > 4 && map[4]=='2') { |
- size_t skip = zi_dotprod(zi+20, VEC(1,1,8,5,6,1), 6); |
- trans = zi+skip+44+44; |
- scale++; |
- } else { |
- trans = zi+44; |
- } |
- index = trans + (zi_read32(trans-12) << scale); |
- types = index + zi_read32(trans-12); |
- abbrevs = types + 6*zi_read32(trans-8); |
- abbrevs_end = abbrevs + zi_read32(trans-4); |
- if (zi[map_size-1] == '\n') { |
- for (s = (const char *)zi+map_size-2; *s!='\n'; s--); |
- s++; |
- } else { |
- const unsigned char *p; |
- __tzname[0] = __tzname[1] = 0; |
- __daylight = __timezone = dst_off = 0; |
- for (i=0; i<5; i++) r0[i] = r1[i] = 0; |
- for (p=types; p<abbrevs; p+=6) { |
- if (!p[4] && !__tzname[0]) { |
- __tzname[0] = (char *)abbrevs + p[5]; |
- __timezone = -zi_read32(p); |
- } |
- if (p[4] && !__tzname[1]) { |
- __tzname[1] = (char *)abbrevs + p[5]; |
- dst_off = -zi_read32(p); |
- __daylight = 1; |
- } |
- } |
- if (!__tzname[0]) __tzname[0] = __tzname[1]; |
- if (!__tzname[0]) __tzname[0] = (char *)__gmt; |
- if (!__daylight) { |
- __tzname[1] = __tzname[0]; |
- dst_off = __timezone; |
- } |
- return; |
- } |
- } |
- |
- if (!s) s = __gmt; |
- getname(std_name, &s); |
- __tzname[0] = std_name; |
- __timezone = getoff(&s); |
- getname(dst_name, &s); |
- __tzname[1] = dst_name; |
- if (dst_name[0]) { |
- __daylight = 1; |
- if (*s == '+' || *s=='-' || *s-'0'<10U) |
- dst_off = getoff(&s); |
- else |
- dst_off = __timezone - 3600; |
- } else { |
- __daylight = 0; |
- dst_off = 0; |
- } |
- |
- if (*s == ',') s++, getrule(&s, r0); |
- if (*s == ',') s++, getrule(&s, r1); |
+int __munmap(void*, size_t); |
+ |
+static void do_tzset() { |
+ char buf[NAME_MAX + 25], *pathname = buf + 24; |
+ const char* try |
+ , *s, *p; |
+ const unsigned char* map = 0; |
+ size_t i; |
+ static const char search[] = |
+ "/usr/share/zoneinfo/\0/share/zoneinfo/\0/etc/zoneinfo/\0"; |
+ |
+ s = getenv("TZ"); |
+ if (!s) |
+ s = "/etc/localtime"; |
+ if (!*s) |
+ s = __gmt; |
+ |
+ if (old_tz && !strcmp(s, old_tz)) |
+ return; |
+ |
+ if (zi) |
+ __munmap((void*)zi, map_size); |
+ |
+ /* Cache the old value of TZ to check if it has changed. Avoid |
+ * free so as not to pull it into static programs. Growth |
+ * strategy makes it so free would have minimal benefit anyway. */ |
+ i = strlen(s); |
+ if (i > PATH_MAX + 1) |
+ s = __gmt, i = 3; |
+ if (i >= old_tz_size) { |
+ old_tz_size *= 2; |
+ if (i >= old_tz_size) |
+ old_tz_size = i + 1; |
+ if (old_tz_size > PATH_MAX + 2) |
+ old_tz_size = PATH_MAX + 2; |
+ old_tz = malloc(old_tz_size); |
+ } |
+ if (old_tz) |
+ memcpy(old_tz, s, i + 1); |
+ |
+ /* Non-suid can use an absolute tzfile pathname or a relative |
+ * pathame beginning with "."; in secure mode, only the |
+ * standard path will be searched. */ |
+ if (*s == ':' || ((p = strchr(s, '/')) && !memchr(s, ',', p - s))) { |
+ if (*s == ':') |
+ s++; |
+ if (*s == '/' || *s == '.') { |
+ if (!libc.secure || !strcmp(s, "/etc/localtime")) |
+ map = __map_file(s, &map_size); |
+ } else { |
+ size_t l = strlen(s); |
+ if (l <= NAME_MAX && !strchr(s, '.')) { |
+ memcpy(pathname, s, l + 1); |
+ pathname[l] = 0; |
+ for (try = search; !map && *try; try += l + 1) { |
+ l = strlen(try); |
+ memcpy(pathname - l, try, l); |
+ map = __map_file(pathname - l, &map_size); |
+ } |
+ } |
+ } |
+ if (!map) |
+ s = __gmt; |
+ } |
+ if (map && (map_size < 44 || memcmp(map, "TZif", 4))) { |
+ __munmap((void*)map, map_size); |
+ map = 0; |
+ s = __gmt; |
+ } |
+ |
+ zi = map; |
+ if (map) { |
+ int scale = 2; |
+ if (sizeof(time_t) > 4 && map[4] == '2') { |
+ size_t skip = zi_dotprod(zi + 20, VEC(1, 1, 8, 5, 6, 1), 6); |
+ trans = zi + skip + 44 + 44; |
+ scale++; |
+ } else { |
+ trans = zi + 44; |
+ } |
+ index = trans + (zi_read32(trans - 12) << scale); |
+ types = index + zi_read32(trans - 12); |
+ abbrevs = types + 6 * zi_read32(trans - 8); |
+ abbrevs_end = abbrevs + zi_read32(trans - 4); |
+ if (zi[map_size - 1] == '\n') { |
+ for (s = (const char*)zi + map_size - 2; *s != '\n'; s--) |
+ ; |
+ s++; |
+ } else { |
+ const unsigned char* p; |
+ __tzname[0] = __tzname[1] = 0; |
+ __daylight = __timezone = dst_off = 0; |
+ for (i = 0; i < 5; i++) |
+ r0[i] = r1[i] = 0; |
+ for (p = types; p < abbrevs; p += 6) { |
+ if (!p[4] && !__tzname[0]) { |
+ __tzname[0] = (char*)abbrevs + p[5]; |
+ __timezone = -zi_read32(p); |
+ } |
+ if (p[4] && !__tzname[1]) { |
+ __tzname[1] = (char*)abbrevs + p[5]; |
+ dst_off = -zi_read32(p); |
+ __daylight = 1; |
+ } |
+ } |
+ if (!__tzname[0]) |
+ __tzname[0] = __tzname[1]; |
+ if (!__tzname[0]) |
+ __tzname[0] = (char*)__gmt; |
+ if (!__daylight) { |
+ __tzname[1] = __tzname[0]; |
+ dst_off = __timezone; |
+ } |
+ return; |
+ } |
+ } |
+ |
+ if (!s) |
+ s = __gmt; |
+ getname(std_name, &s); |
+ __tzname[0] = std_name; |
+ __timezone = getoff(&s); |
+ getname(dst_name, &s); |
+ __tzname[1] = dst_name; |
+ if (dst_name[0]) { |
+ __daylight = 1; |
+ if (*s == '+' || *s == '-' || *s - '0' < 10U) |
+ dst_off = getoff(&s); |
+ else |
+ dst_off = __timezone - 3600; |
+ } else { |
+ __daylight = 0; |
+ dst_off = 0; |
+ } |
+ |
+ if (*s == ',') |
+ s++, getrule(&s, r0); |
+ if (*s == ',') |
+ s++, getrule(&s, r1); |
} |
/* Search zoneinfo rules to find the one that applies to the given time, |
* and determine alternate opposite-DST-status rule that may be needed. */ |
-static size_t scan_trans(long long t, int local, size_t *alt) |
-{ |
- int scale = 3 - (trans == zi+44); |
- uint64_t x; |
- int off = 0; |
- |
- size_t a = 0, n = (index-trans)>>scale, m; |
- |
- if (!n) { |
- if (alt) *alt = 0; |
- return 0; |
- } |
- |
- /* Binary search for 'most-recent rule before t'. */ |
- while (n > 1) { |
- m = a + n/2; |
- x = zi_read32(trans + (m<<scale)); |
- if (scale == 3) x = x<<32 | zi_read32(trans + (m<<scale) + 4); |
- else x = (int32_t)x; |
- if (local) off = (int32_t)zi_read32(types + 6 * index[m-1]); |
- if (t - off < (int64_t)x) { |
- n /= 2; |
- } else { |
- a = m; |
- n -= n/2; |
- } |
- } |
- |
- /* First and last entry are special. First means to use lowest-index |
- * non-DST type. Last means to apply POSIX-style rule if available. */ |
- n = (index-trans)>>scale; |
- if (a == n-1) return -1; |
- if (a == 0) { |
- x = zi_read32(trans + (a<<scale)); |
- if (scale == 3) x = x<<32 | zi_read32(trans + (a<<scale) + 4); |
- else x = (int32_t)x; |
- if (local) off = (int32_t)zi_read32(types + 6 * index[a-1]); |
- if (t - off < (int64_t)x) { |
- for (a=0; a<(abbrevs-types)/6; a++) { |
- if (types[6*a+4] != types[4]) break; |
- } |
- if (a == (abbrevs-types)/6) a = 0; |
- if (types[6*a+4]) { |
- *alt = a; |
- return 0; |
- } else { |
- *alt = 0; |
- return a; |
- } |
- } |
- } |
- |
- /* Try to find a neighboring opposite-DST-status rule. */ |
- if (alt) { |
- if (a && types[6*index[a-1]+4] != types[6*index[a]+4]) |
- *alt = index[a-1]; |
- else if (a+1<n && types[6*index[a+1]+4] != types[6*index[a]+4]) |
- *alt = index[a+1]; |
- else |
- *alt = index[a]; |
- } |
- |
- return index[a]; |
+static size_t scan_trans(long long t, int local, size_t* alt) { |
+ int scale = 3 - (trans == zi + 44); |
+ uint64_t x; |
+ int off = 0; |
+ |
+ size_t a = 0, n = (index - trans) >> scale, m; |
+ |
+ if (!n) { |
+ if (alt) |
+ *alt = 0; |
+ return 0; |
+ } |
+ |
+ /* Binary search for 'most-recent rule before t'. */ |
+ while (n > 1) { |
+ m = a + n / 2; |
+ x = zi_read32(trans + (m << scale)); |
+ if (scale == 3) |
+ x = x << 32 | zi_read32(trans + (m << scale) + 4); |
+ else |
+ x = (int32_t)x; |
+ if (local) |
+ off = (int32_t)zi_read32(types + 6 * index[m - 1]); |
+ if (t - off < (int64_t)x) { |
+ n /= 2; |
+ } else { |
+ a = m; |
+ n -= n / 2; |
+ } |
+ } |
+ |
+ /* First and last entry are special. First means to use lowest-index |
+ * non-DST type. Last means to apply POSIX-style rule if available. */ |
+ n = (index - trans) >> scale; |
+ if (a == n - 1) |
+ return -1; |
+ if (a == 0) { |
+ x = zi_read32(trans + (a << scale)); |
+ if (scale == 3) |
+ x = x << 32 | zi_read32(trans + (a << scale) + 4); |
+ else |
+ x = (int32_t)x; |
+ if (local) |
+ off = (int32_t)zi_read32(types + 6 * index[a - 1]); |
+ if (t - off < (int64_t)x) { |
+ for (a = 0; a < (abbrevs - types) / 6; a++) { |
+ if (types[6 * a + 4] != types[4]) |
+ break; |
+ } |
+ if (a == (abbrevs - types) / 6) |
+ a = 0; |
+ if (types[6 * a + 4]) { |
+ *alt = a; |
+ return 0; |
+ } else { |
+ *alt = 0; |
+ return a; |
+ } |
+ } |
+ } |
+ |
+ /* Try to find a neighboring opposite-DST-status rule. */ |
+ if (alt) { |
+ if (a && types[6 * index[a - 1] + 4] != types[6 * index[a] + 4]) |
+ *alt = index[a - 1]; |
+ else if (a + 1 < n && |
+ types[6 * index[a + 1] + 4] != types[6 * index[a] + 4]) |
+ *alt = index[a + 1]; |
+ else |
+ *alt = index[a]; |
+ } |
+ |
+ return index[a]; |
} |
-static int days_in_month(int m, int is_leap) |
-{ |
- if (m==2) return 28+is_leap; |
- else return 30+((0xad5>>(m-1))&1); |
+static int days_in_month(int m, int is_leap) { |
+ if (m == 2) |
+ return 28 + is_leap; |
+ else |
+ return 30 + ((0xad5 >> (m - 1)) & 1); |
} |
/* Convert a POSIX DST rule plus year to seconds since epoch. */ |
-static long long rule_to_secs(const int *rule, int year) |
-{ |
- int is_leap; |
- long long t = __year_to_secs(year, &is_leap); |
- int x, m, n, d; |
- if (rule[0]!='M') { |
- x = rule[1]; |
- if (rule[0]=='J' && (x < 60 || !is_leap)) x--; |
- t += 86400 * x; |
- } else { |
- m = rule[1]; |
- n = rule[2]; |
- d = rule[3]; |
- t += __month_to_secs(m-1, is_leap); |
- int wday = (int)((t + 4*86400) % (7*86400)) / 86400; |
- int days = d - wday; |
- if (days < 0) days += 7; |
- if (n == 5 && days+28 >= days_in_month(m, is_leap)) n = 4; |
- t += 86400 * (days + 7*(n-1)); |
- } |
- t += rule[4]; |
- return t; |
+static long long rule_to_secs(const int* rule, int year) { |
+ int is_leap; |
+ long long t = __year_to_secs(year, &is_leap); |
+ int x, m, n, d; |
+ if (rule[0] != 'M') { |
+ x = rule[1]; |
+ if (rule[0] == 'J' && (x < 60 || !is_leap)) |
+ x--; |
+ t += 86400 * x; |
+ } else { |
+ m = rule[1]; |
+ n = rule[2]; |
+ d = rule[3]; |
+ t += __month_to_secs(m - 1, is_leap); |
+ int wday = (int)((t + 4 * 86400) % (7 * 86400)) / 86400; |
+ int days = d - wday; |
+ if (days < 0) |
+ days += 7; |
+ if (n == 5 && days + 28 >= days_in_month(m, is_leap)) |
+ n = 4; |
+ t += 86400 * (days + 7 * (n - 1)); |
+ } |
+ t += rule[4]; |
+ return t; |
} |
/* Determine the time zone in effect for a given time in seconds since the |
@@ -344,82 +376,92 @@ static long long rule_to_secs(const int *rule, int year) |
* enables a caller to efficiently adjust for the case where an explicit |
* DST specification mismatches what would be in effect at the time. */ |
-void __secs_to_zone(long long t, int local, int *isdst, long *offset, long *oppoff, const char **zonename) |
-{ |
- LOCK(lock); |
- |
- do_tzset(); |
- |
- if (zi) { |
- size_t alt, i = scan_trans(t, local, &alt); |
- if (i != -1) { |
- *isdst = types[6*i+4]; |
- *offset = (int32_t)zi_read32(types+6*i); |
- *zonename = (const char *)abbrevs + types[6*i+5]; |
- if (oppoff) *oppoff = (int32_t)zi_read32(types+6*alt); |
- UNLOCK(lock); |
- return; |
- } |
- } |
- |
- if (!__daylight) goto std; |
- |
- /* FIXME: may be broken if DST changes right at year boundary? |
- * Also, this could be more efficient.*/ |
- long long y = t / 31556952 + 70; |
- while (__year_to_secs(y, 0) > t) y--; |
- while (__year_to_secs(y+1, 0) < t) y++; |
- |
- long long t0 = rule_to_secs(r0, y); |
- long long t1 = rule_to_secs(r1, y); |
- |
- if (t0 < t1) { |
- if (!local) { |
- t0 += __timezone; |
- t1 += dst_off; |
- } |
- if (t >= t0 && t < t1) goto dst; |
- goto std; |
- } else { |
- if (!local) { |
- t1 += __timezone; |
- t0 += dst_off; |
- } |
- if (t >= t1 && t < t0) goto std; |
- goto dst; |
- } |
+void __secs_to_zone(long long t, |
+ int local, |
+ int* isdst, |
+ long* offset, |
+ long* oppoff, |
+ const char** zonename) { |
+ LOCK(lock); |
+ |
+ do_tzset(); |
+ |
+ if (zi) { |
+ size_t alt, i = scan_trans(t, local, &alt); |
+ if (i != -1) { |
+ *isdst = types[6 * i + 4]; |
+ *offset = (int32_t)zi_read32(types + 6 * i); |
+ *zonename = (const char*)abbrevs + types[6 * i + 5]; |
+ if (oppoff) |
+ *oppoff = (int32_t)zi_read32(types + 6 * alt); |
+ UNLOCK(lock); |
+ return; |
+ } |
+ } |
+ |
+ if (!__daylight) |
+ goto std; |
+ |
+ /* FIXME: may be broken if DST changes right at year boundary? |
+ * Also, this could be more efficient.*/ |
+ long long y = t / 31556952 + 70; |
+ while (__year_to_secs(y, 0) > t) |
+ y--; |
+ while (__year_to_secs(y + 1, 0) < t) |
+ y++; |
+ |
+ long long t0 = rule_to_secs(r0, y); |
+ long long t1 = rule_to_secs(r1, y); |
+ |
+ if (t0 < t1) { |
+ if (!local) { |
+ t0 += __timezone; |
+ t1 += dst_off; |
+ } |
+ if (t >= t0 && t < t1) |
+ goto dst; |
+ goto std; |
+ } else { |
+ if (!local) { |
+ t1 += __timezone; |
+ t0 += dst_off; |
+ } |
+ if (t >= t1 && t < t0) |
+ goto std; |
+ goto dst; |
+ } |
std: |
- *isdst = 0; |
- *offset = -__timezone; |
- if (oppoff) *oppoff = -dst_off; |
- *zonename = __tzname[0]; |
- UNLOCK(lock); |
- return; |
+ *isdst = 0; |
+ *offset = -__timezone; |
+ if (oppoff) |
+ *oppoff = -dst_off; |
+ *zonename = __tzname[0]; |
+ UNLOCK(lock); |
+ return; |
dst: |
- *isdst = 1; |
- *offset = -dst_off; |
- if (oppoff) *oppoff = -__timezone; |
- *zonename = __tzname[1]; |
- UNLOCK(lock); |
+ *isdst = 1; |
+ *offset = -dst_off; |
+ if (oppoff) |
+ *oppoff = -__timezone; |
+ *zonename = __tzname[1]; |
+ UNLOCK(lock); |
} |
-void __tzset() |
-{ |
- LOCK(lock); |
- do_tzset(); |
- UNLOCK(lock); |
+void __tzset() { |
+ LOCK(lock); |
+ do_tzset(); |
+ UNLOCK(lock); |
} |
weak_alias(__tzset, tzset); |
-const char *__tm_to_tzname(const struct tm *tm) |
-{ |
- const void *p = tm->__tm_zone; |
- LOCK(lock); |
- do_tzset(); |
- if (p != __gmt && p != __tzname[0] && p != __tzname[1] && |
- (!zi || (uintptr_t)p-(uintptr_t)abbrevs >= abbrevs_end - abbrevs)) |
- p = ""; |
- UNLOCK(lock); |
- return p; |
+const char* __tm_to_tzname(const struct tm* tm) { |
+ const void* p = tm->__tm_zone; |
+ LOCK(lock); |
+ do_tzset(); |
+ if (p != __gmt && p != __tzname[0] && p != __tzname[1] && |
+ (!zi || (uintptr_t)p - (uintptr_t)abbrevs >= abbrevs_end - abbrevs)) |
+ p = ""; |
+ UNLOCK(lock); |
+ return p; |
} |