From 2856b1dd6f0ff5164eb5a54ddfadb9963f9e9237 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Mon, 27 Jul 2015 16:50:44 -0700 Subject: [PATCH] Merge from gnulib This incorporates: 2015-07-27 time_rz: port better to MinGW 2015-07-27 time: port __need_time_t to MinGW * lib/gnulib.mk, m4/gnulib-comp.m4: Regenerate. * lib/strftime.c, lib/time.in.h, lib/time_rz.c: Copy from gnulib. * lib/time-internal.h: New file, from gnulib. --- lib/gnulib.mk | 2 +- lib/strftime.c | 10 ++++- lib/time-internal.h | 49 +++++++++++++++++++++++ lib/time.in.h | 12 +++--- lib/time_rz.c | 98 +++++++++++---------------------------------- m4/gnulib-comp.m4 | 1 + 6 files changed, 90 insertions(+), 82 deletions(-) create mode 100644 lib/time-internal.h diff --git a/lib/gnulib.mk b/lib/gnulib.mk index 1ca12a28be..67c7e18401 100644 --- a/lib/gnulib.mk +++ b/lib/gnulib.mk @@ -1640,7 +1640,7 @@ EXTRA_libgnu_a_SOURCES += time_r.c ## begin gnulib module time_rz -EXTRA_DIST += time_rz.c +EXTRA_DIST += time-internal.h time_rz.c EXTRA_libgnu_a_SOURCES += time_rz.c diff --git a/lib/strftime.c b/lib/strftime.c index c7cec2621c..d1ca346b68 100644 --- a/lib/strftime.c +++ b/lib/strftime.c @@ -30,6 +30,7 @@ # else # include "strftime.h" # endif +# include "time-internal.h" #endif #include @@ -439,6 +440,9 @@ strftime_case_ (bool upcase, STREAM_OR_CHAR_T *s, # define aw_len STRLEN (a_wkday) # 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; @@ -475,6 +479,10 @@ strftime_case_ (bool upcase, STREAM_OR_CHAR_T *s, } 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 @@ strftime_case_ (bool upcase, STREAM_OR_CHAR_T *s, } /* 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 = ""; diff --git a/lib/time-internal.h b/lib/time-internal.h new file mode 100644 index 0000000000..6bf3f8d30b --- /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 3, 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 . */ + +/* 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]; +}; diff --git a/lib/time.in.h b/lib/time.in.h index 1adfe92539..a90552ce44 100644 --- a/lib/time.in.h +++ b/lib/time.in.h @@ -22,13 +22,13 @@ /* Don't get in the way of glibc when it includes time.h merely to declare a few standard symbols, rather than to declare all the - symbols. Also, Solaris 8 eventually includes itself + symbols. (However, skip this for MinGW as it treats __need_time_t + incompatibly.) Also, Solaris 8 eventually includes itself recursively; if that is happening, just include the system - without adding our own declarations. MinGW system headers use - these symbols as well, but we don't want to exclude MinGW from the - 'else' branch below. */ -#if (((defined __need_time_t || defined __need_clock_t \ - || defined __need_timespec) && !defined __MINGW32__) \ + without adding our own declarations. */ +#if (((defined __need_time_t || defined __need_clock_t \ + || defined __need_timespec) \ + && !defined __MINGW32__) \ || defined _@GUARD_PREFIX@_TIME_H) # @INCLUDE_NEXT@ @NEXT_TIME_H@ diff --git a/lib/time_rz.c b/lib/time_rz.c index 8a4d7d13a2..cbbe2c6ac2 100644 --- a/lib/time_rz.c +++ b/lib/time_rz.c @@ -32,35 +32,12 @@ #include #include +#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 @@ tzalloc (char const *name) 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 @@ save_abbr (timezone_t tz, struct tm *tm) /* 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 @@ revert_tz (timezone_t tz) 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 @@ localtime_rz (timezone_t tz, time_t const *t, struct tm *tm) time_t mktime_z (timezone_t tz, struct tm *tm) { - restore_tzname (); - if (!tz) return timegm (tm); else diff --git a/m4/gnulib-comp.m4 b/m4/gnulib-comp.m4 index cf71d7eb18..c48d2e5be5 100644 --- a/m4/gnulib-comp.m4 +++ b/m4/gnulib-comp.m4 @@ -959,6 +959,7 @@ AC_DEFUN([gl_FILE_LIST], [ lib/sys_types.in.h lib/tempname.c lib/tempname.h + lib/time-internal.h lib/time.in.h lib/time_r.c lib/time_rz.c -- 2.39.2