Mercurial > hg > octave-jordi > gnulib-hg
changeset 18069:1c6c8e9218c9
time_rz: port better to MinGW
Don't change tzname, as this makes MinGW dump core (Bug#21020).
Instead, store the tzname copy in the struct tm_zone object.
Problem reported by Eli Zaretskii in: http://bugs.gnu.org/21020#48
* lib/strftime.c [!_LIBC]:
* lib/time_rz.c: Include time-internal.h.
* lib/strftime.c (strftime_case_) [!HAVE_TM_ZONE]: Infer the zone
name from *TZ rather than from TZNAME, doable because *TZ now has
a tzname_copy member.
* lib/time-internal.h: New file, with contents taken from
lib/time_rz.c. It's separate because strftime.c now accesses
struct tm_zone members.
(struct tm_zone) [HAVE_TZNAME && !HAVE_TM_ZONE]:
New member tzname_copy.
* lib/time_rz.c (struct tm_zone): Move to time-internal.h.
(tzalloc) [HAVE_TZNAME && !HAVE_TM_ZONE]:
Initialize tzname_copy member.
(save_abbr) [HAVE_TZNAME && !HAVE_TM_ZONE]: Save abbreviation
in tzname_copy member.
(revert_tz) [HAVE_TZNAME]: Remove no-longer-needed tzname saving.
(restore_tzname): Remove; no longer needed. All calls removed.
* modules/time_rz (Files): Add lib/time-internal.h.
author | Paul Eggert <eggert@cs.ucla.edu> |
---|---|
date | Mon, 27 Jul 2015 16:41:17 -0700 |
parents | 90195ad97c8b |
children | d460ec17f09f |
files | ChangeLog lib/strftime.c lib/time-internal.h lib/time_rz.c modules/time_rz |
diffstat | 5 files changed, 106 insertions(+), 75 deletions(-) [+] |
line wrap: on
line diff
--- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,28 @@ 2015-07-27 Paul Eggert <eggert@cs.ucla.edu> + time_rz: port better to MinGW + Don't change tzname, as this makes MinGW dump core (Bug#21020). + Instead, store the tzname copy in the struct tm_zone object. + Problem reported by Eli Zaretskii in: http://bugs.gnu.org/21020#48 + * lib/strftime.c [!_LIBC]: + * lib/time_rz.c: Include time-internal.h. + * lib/strftime.c (strftime_case_) [!HAVE_TM_ZONE]: Infer the zone + name from *TZ rather than from TZNAME, doable because *TZ now has + a tzname_copy member. + * lib/time-internal.h: New file, with contents taken from + lib/time_rz.c. It's separate because strftime.c now accesses + struct tm_zone members. + (struct tm_zone) [HAVE_TZNAME && !HAVE_TM_ZONE]: + New member tzname_copy. + * lib/time_rz.c (struct tm_zone): Move to time-internal.h. + (tzalloc) [HAVE_TZNAME && !HAVE_TM_ZONE]: + Initialize tzname_copy member. + (save_abbr) [HAVE_TZNAME && !HAVE_TM_ZONE]: Save abbreviation + in tzname_copy member. + (revert_tz) [HAVE_TZNAME]: Remove no-longer-needed tzname saving. + (restore_tzname): Remove; no longer needed. All calls removed. + * modules/time_rz (Files): Add lib/time-internal.h. + time: port __need_time_t to MinGW * lib/time.in.h (__need_time_t): Do not treat specially on MinGW. Fix reported by Eli Zaretskii in: http://bugs.gnu.org/21020#36
--- a/lib/strftime.c +++ b/lib/strftime.c @@ -30,6 +30,7 @@ # else # include "strftime.h" # endif +# include "time-internal.h" #endif #include <ctype.h> @@ -440,6 +441,9 @@ # define am_len STRLEN (a_month) # define ap_len STRLEN (ampm) #endif +#if HAVE_TZNAME + char **tzname_vec = tzname; +#endif const char *zone; size_t i = 0; STREAM_OR_CHAR_T *p = s; @@ -475,6 +479,10 @@ } else { +# if !HAVE_TM_ZONE + /* Infer the zone name from *TZ instead of from TZNAME. */ + tzname_vec = tz->tzname_copy; +# endif /* POSIX.1 requires that local time zone information be used as though strftime called tzset. */ # if HAVE_TZSET @@ -483,7 +491,7 @@ } /* The tzset() call might have changed the value. */ if (!(zone && *zone) && tp->tm_isdst >= 0) - zone = tzname[tp->tm_isdst != 0]; + zone = tzname_vec[tp->tm_isdst != 0]; #endif if (! zone) zone = "";
new file mode 100644 --- /dev/null +++ b/lib/time-internal.h @@ -0,0 +1,49 @@ +/* Time internal interface + + Copyright 2015 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, see <http://www.gnu.org/licenses/>. */ + +/* Written by Paul Eggert. */ + +/* A time zone rule. */ +struct tm_zone +{ + /* More abbreviations, should they be needed. Their TZ_IS_SET + members are zero. */ + struct tm_zone *next; + +#if HAVE_TZNAME && !HAVE_TM_ZONE + /* Copies of recent strings taken from tzname[0] and tzname[1]. + The copies are in ABBRS, so that they survive tzset. Null if unknown. */ + char *tzname_copy[2]; +#endif + + /* If nonzero, the rule represents the TZ environment variable set + to the first "abbreviation" (this may be the empty string). + Otherwise, it represents an unset TZ. */ + char tz_is_set; + + /* A sequence of null-terminated strings packed next to each other. + The strings are followed by an extra null byte. If TZ_IS_SET, + there must be at least one string and the first string (which is + actually a TZ environment value value) may be empty. Otherwise + all strings must be nonempty. + + Abbreviations are stored here because otherwise the values of + tm_zone and/or tzname would be dead after changing TZ and calling + tzset. Abbreviations never move once allocated, and are live + until tzfree is called. */ + char abbrs[FLEXIBLE_ARRAY_MEMBER]; +};
--- a/lib/time_rz.c +++ b/lib/time_rz.c @@ -32,35 +32,12 @@ #include <stdlib.h> #include <string.h> +#include "time-internal.h" + #if !HAVE_TZSET static void tzset (void) { } #endif -/* A time zone rule. */ -struct tm_zone -{ - /* More abbreviations, should they be needed. Their TZ_IS_SET - members are zero. */ - timezone_t next; - - /* If nonzero, the rule represents the TZ environment variable set - to the first "abbreviation" (this may be the empty string). - Otherwise, it represents an unset TZ. */ - char tz_is_set; - - /* A sequence of null-terminated strings packed next to each other. - The strings are followed by an extra null byte. If TZ_IS_SET, - there must be at least one string and the first string (which is - actually a TZ environment value value) may be empty. Otherwise - all strings must be nonempty. - - Abbreviations are stored here because otherwise the values of - tm_zone and/or tzname would be dead after changing TZ and calling - tzset. Abbreviations never move once allocated, and are live - until tzfree is called. */ - char abbrs[FLEXIBLE_ARRAY_MEMBER]; -}; - /* The approximate size to use for small allocation requests. This is the largest "small" request for the GNU C library malloc. */ enum { DEFAULT_MXFAST = 64 * sizeof (size_t) / 4 }; @@ -124,39 +101,40 @@ if (tz) { tz->next = NULL; +#if HAVE_TZNAME && !HAVE_TM_ZONE + tz->tzname_copy[0] = tz->tzname_copy[1] = NULL; +#endif tz->tz_is_set = !!name; extend_abbrs (tz->abbrs, name, name_size); } return tz; } -#if HAVE_TZNAME -/* If TZNAME_ADDRESS is nonnull, an assignment of a saved abbreviation. - TZNAME_ADDRESS should be either null, or &tzname[0], or &tzname[1]. - *TZNAME_ADDRESS = TZNAME_VALUE should be done after revert_tz - (indirectly) calls tzset, so that revert_tz can overwrite tzset's - assignment to tzname. Also, it should be done at the start of - the next localtime_tz or mktime_z, to undo the overwrite. */ -static char **tzname_address; -static char *tzname_value; -#endif - -/* Save into TZ any nontrivial time zone abbreviation used by TM, - and update *TM (or prepare to update tzname) if they use the abbreviation. - Return true if successful, false (setting errno) otherwise. */ +/* Save into TZ any nontrivial time zone abbreviation used by TM, and + update *TM (if HAVE_TM_ZONE) or *TZ (if !HAVE_TM_ZONE && + HAVE_TZNAME) if they use the abbreviation. Return true if + successful, false (setting errno) otherwise. */ static bool save_abbr (timezone_t tz, struct tm *tm) { #if HAVE_TM_ZONE || HAVE_TZNAME char const *zone = NULL; - char **tzname_zone = NULL; char *zone_copy = (char *) ""; + +# if HAVE_TZNAME + int tzname_index = -1; +# endif + # if HAVE_TM_ZONE zone = tm->tm_zone; # endif + # if HAVE_TZNAME if (! (zone && *zone) && 0 <= tm->tm_isdst) - zone = *(tzname_zone = &tzname[0 < tm->tm_isdst]); + { + tzname_index = tm->tm_isdst != 0; + zone = tzname[tzname_index]; + } # endif /* No need to replace null zones, or zones within the struct tm. */ @@ -196,14 +174,13 @@ /* Replace the zone name so that its lifetime matches that of TZ. */ # if HAVE_TM_ZONE - if (!tzname_zone) - tm->tm_zone = zone_copy; -# endif -# if HAVE_TZNAME - tzname_address = tzname_zone; - tzname_value = zone_copy; + tm->tm_zone = zone_copy; +# else + if (0 <= tzname_index) + tz->tzname_copy[tzname_index] = zone_copy; # endif #endif + return true; } @@ -292,41 +269,16 @@ bool ok = change_env (tz); if (!ok) saved_errno = errno; -#if HAVE_TZNAME - if (!ok) - tzname_address = NULL; - if (tzname_address) - { - char *old_value = *tzname_address; - *tzname_address = tzname_value; - tzname_value = old_value; - } -#endif tzfree (tz); errno = saved_errno; return ok; } } -/* Restore an old tzname setting that was temporarily munged by revert_tz. */ -static void -restore_tzname (void) -{ -#if HAVE_TZNAME - if (tzname_address) - { - *tzname_address = tzname_value; - tzname_address = NULL; - } -#endif -} - /* Use time zone TZ to compute localtime_r (T, TM). */ struct tm * localtime_rz (timezone_t tz, time_t const *t, struct tm *tm) { - restore_tzname (); - if (!tz) return gmtime_r (t, tm); else @@ -348,8 +300,6 @@ time_t mktime_z (timezone_t tz, struct tm *tm) { - restore_tzname (); - if (!tz) return timegm (tm); else