diff options
Diffstat (limited to 'time/tzset.c')
-rw-r--r-- | time/tzset.c | 230 |
1 files changed, 122 insertions, 108 deletions
diff --git a/time/tzset.c b/time/tzset.c index 0479abb38a..27efef0f7a 100644 --- a/time/tzset.c +++ b/time/tzset.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2002,2003,2004 Free Software Foundation, Inc. +/* Copyright (C) 1991-2002,2003,2004,2007 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -70,7 +70,6 @@ static tz_rule tz_rules[2]; static void compute_change (tz_rule *rule, int year) __THROW internal_function; -static void tz_compute (const struct tm *tm) __THROW internal_function; static void tzset_internal (int always, int explicit) __THROW internal_function; @@ -92,7 +91,7 @@ __tzstring (const char *s) { char *p; struct tzstring_l *t, *u, *new; - size_t len = strlen(s); + size_t len = strlen (s); /* Walk the list and look for a match. If this string is the same as the end of an already-allocated string, it can share space. */ @@ -140,80 +139,34 @@ __tzname_max () static char *old_tz; -/* Interpret the TZ envariable. */ static void internal_function -tzset_internal (always, explicit) - int always; - int explicit; +update_vars (void) +{ + __daylight = tz_rules[0].offset != tz_rules[1].offset; + __timezone = -tz_rules[0].offset; + __tzname[0] = (char *) tz_rules[0].name; + __tzname[1] = (char *) tz_rules[1].name; + + /* Keep __tzname_cur_max up to date. */ + size_t len0 = strlen (__tzname[0]); + size_t len1 = strlen (__tzname[1]); + if (len0 > __tzname_cur_max) + __tzname_cur_max = len0; + if (len1 > __tzname_cur_max) + __tzname_cur_max = len1; +} + +/* Parse the POSIX TZ-style string. */ +void +__tzset_parse_tz (tz) + const char *tz; { - static int is_initialized; - register const char *tz; register size_t l; char *tzbuf; unsigned short int hh, mm, ss; unsigned short int whichrule; - if (is_initialized && !always) - return; - is_initialized = 1; - - /* Examine the TZ environment variable. */ - tz = getenv ("TZ"); - if (tz == NULL && !explicit) - /* Use the site-wide default. This is a file name which means we - would not see changes to the file if we compare only the file - name for change. We want to notice file changes if tzset() has - been called explicitly. Leave TZ as NULL in this case. */ - tz = TZDEFAULT; - if (tz && *tz == '\0') - /* User specified the empty string; use UTC explicitly. */ - tz = "Universal"; - - /* A leading colon means "implementation defined syntax". - We ignore the colon and always use the same algorithm: - try a data file, and if none exists parse the 1003.1 syntax. */ - if (tz && *tz == ':') - ++tz; - - /* Check whether the value changes since the last run. */ - if (old_tz != NULL && tz != NULL && strcmp (tz, old_tz) == 0) - /* No change, simply return. */ - return; - - if (tz == NULL) - /* No user specification; use the site-wide default. */ - tz = TZDEFAULT; - - tz_rules[0].name = NULL; - tz_rules[1].name = NULL; - - /* Save the value of `tz'. */ - if (old_tz != NULL) - free (old_tz); - old_tz = tz ? __strdup (tz) : NULL; - - /* Try to read a data file. */ - __tzfile_read (tz, 0, NULL); - if (__use_tzfile) - return; - - /* No data file found. Default to UTC if nothing specified. */ - - if (tz == NULL || *tz == '\0' - || (TZDEFAULT != NULL && strcmp (tz, TZDEFAULT) == 0)) - { - tz_rules[0].name = tz_rules[1].name = "UTC"; - tz_rules[0].type = tz_rules[1].type = J0; - tz_rules[0].m = tz_rules[0].n = tz_rules[0].d = 0; - tz_rules[1].m = tz_rules[1].n = tz_rules[1].d = 0; - tz_rules[0].secs = tz_rules[1].secs = 0; - tz_rules[0].offset = tz_rules[1].offset = 0L; - tz_rules[0].change = tz_rules[1].change = (time_t) -1; - tz_rules[0].computed_for = tz_rules[1].computed_for = 0; - goto out; - } - /* Clear out old state and reset to unnamed UTC. */ memset (tz_rules, 0, sizeof tz_rules); tz_rules[0].name = tz_rules[1].name = ""; @@ -413,20 +366,81 @@ tzset_internal (always, explicit) } out: - __daylight = tz_rules[0].offset != tz_rules[1].offset; - __timezone = -tz_rules[0].offset; - __tzname[0] = (char *) tz_rules[0].name; - __tzname[1] = (char *) tz_rules[1].name; + update_vars (); +} - { - /* Keep __tzname_cur_max up to date. */ - size_t len0 = strlen (__tzname[0]); - size_t len1 = strlen (__tzname[1]); - if (len0 > __tzname_cur_max) - __tzname_cur_max = len0; - if (len1 > __tzname_cur_max) - __tzname_cur_max = len1; - } +/* Interpret the TZ envariable. */ +static void +internal_function +tzset_internal (always, explicit) + int always; + int explicit; +{ + static int is_initialized; + register const char *tz; + + if (is_initialized && !always) + return; + is_initialized = 1; + + /* Examine the TZ environment variable. */ + tz = getenv ("TZ"); + if (tz == NULL && !explicit) + /* Use the site-wide default. This is a file name which means we + would not see changes to the file if we compare only the file + name for change. We want to notice file changes if tzset() has + been called explicitly. Leave TZ as NULL in this case. */ + tz = TZDEFAULT; + if (tz && *tz == '\0') + /* User specified the empty string; use UTC explicitly. */ + tz = "Universal"; + + /* A leading colon means "implementation defined syntax". + We ignore the colon and always use the same algorithm: + try a data file, and if none exists parse the 1003.1 syntax. */ + if (tz && *tz == ':') + ++tz; + + /* Check whether the value changes since the last run. */ + if (old_tz != NULL && tz != NULL && strcmp (tz, old_tz) == 0) + /* No change, simply return. */ + return; + + if (tz == NULL) + /* No user specification; use the site-wide default. */ + tz = TZDEFAULT; + + tz_rules[0].name = NULL; + tz_rules[1].name = NULL; + + /* Save the value of `tz'. */ + if (old_tz != NULL) + free (old_tz); + old_tz = tz ? __strdup (tz) : NULL; + + /* Try to read a data file. */ + __tzfile_read (tz, 0, NULL); + if (__use_tzfile) + return; + + /* No data file found. Default to UTC if nothing specified. */ + + if (tz == NULL || *tz == '\0' + || (TZDEFAULT != NULL && strcmp (tz, TZDEFAULT) == 0)) + { + tz_rules[0].name = tz_rules[1].name = "UTC"; + tz_rules[0].type = tz_rules[1].type = J0; + tz_rules[0].m = tz_rules[0].n = tz_rules[0].d = 0; + tz_rules[1].m = tz_rules[1].n = tz_rules[1].d = 0; + tz_rules[0].secs = tz_rules[1].secs = 0; + tz_rules[0].offset = tz_rules[1].offset = 0L; + tz_rules[0].change = tz_rules[1].change = (time_t) -1; + tz_rules[0].computed_for = tz_rules[1].computed_for = 0; + update_vars (); + return; + } + + __tzset_parse_tz (tz); } /* Figure out the exact time (as a time_t) in YEAR @@ -523,13 +537,34 @@ compute_change (rule, year) /* Figure out the correct timezone for TM and set `__tzname', `__timezone', and `__daylight' accordingly. */ -static void +void internal_function -tz_compute (tm) - const struct tm *tm; +__tz_compute (timer, tm, use_localtime) + time_t timer; + struct tm *tm; + int use_localtime; { compute_change (&tz_rules[0], 1900 + tm->tm_year); compute_change (&tz_rules[1], 1900 + tm->tm_year); + + if (use_localtime) + { + int isdst; + + /* We have to distinguish between northern and southern + hemisphere. For the latter the daylight saving time + ends in the next year. */ + if (__builtin_expect (tz_rules[0].change + > tz_rules[1].change, 0)) + isdst = (timer < tz_rules[1].change + || timer >= tz_rules[0].change); + else + isdst = (timer >= tz_rules[0].change + && timer < tz_rules[1].change); + tm->tm_isdst = isdst; + tm->tm_zone = __tzname[isdst]; + tm->tm_gmtoff = tz_rules[isdst].offset; + } } /* Reinterpret the TZ environment variable and set `tzname'. */ @@ -583,35 +618,14 @@ __tz_convert (const time_t *timer, int use_localtime, struct tm *tp) if (! __offtime (timer, 0, tp)) tp = NULL; else - tz_compute (tp); + __tz_compute (*timer, tp, use_localtime); leap_correction = 0L; leap_extra_secs = 0; } if (tp) { - if (use_localtime) - { - if (!__use_tzfile) - { - int isdst; - - /* We have to distinguish between northern and southern - hemisphere. For the latter the daylight saving time - ends in the next year. */ - if (__builtin_expect (tz_rules[0].change - > tz_rules[1].change, 0)) - isdst = (*timer < tz_rules[1].change - || *timer >= tz_rules[0].change); - else - isdst = (*timer >= tz_rules[0].change - && *timer < tz_rules[1].change); - tp->tm_isdst = isdst; - tp->tm_zone = __tzname[isdst]; - tp->tm_gmtoff = tz_rules[isdst].offset; - } - } - else + if (! use_localtime) { tp->tm_isdst = 0; tp->tm_zone = "GMT"; |