diff options
| author | Paul Eggert | 2015-07-27 16:50:44 -0700 |
|---|---|---|
| committer | Paul Eggert | 2015-07-27 16:51:22 -0700 |
| commit | 2856b1dd6f0ff5164eb5a54ddfadb9963f9e9237 (patch) | |
| tree | cff0c4728088e2cfc6939bd4a752c619a54c1cbd /lib | |
| parent | 094d5e9ef0fac319816c00cc52e0a0f2ef41be37 (diff) | |
| download | emacs-2856b1dd6f0ff5164eb5a54ddfadb9963f9e9237.tar.gz emacs-2856b1dd6f0ff5164eb5a54ddfadb9963f9e9237.zip | |
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.
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/gnulib.mk | 2 | ||||
| -rw-r--r-- | lib/strftime.c | 10 | ||||
| -rw-r--r-- | lib/time-internal.h | 49 | ||||
| -rw-r--r-- | lib/time.in.h | 12 | ||||
| -rw-r--r-- | lib/time_rz.c | 98 |
5 files changed, 89 insertions, 82 deletions
diff --git a/lib/gnulib.mk b/lib/gnulib.mk index 1ca12a28beb..67c7e184016 100644 --- a/lib/gnulib.mk +++ b/lib/gnulib.mk | |||
| @@ -1640,7 +1640,7 @@ EXTRA_libgnu_a_SOURCES += time_r.c | |||
| 1640 | ## begin gnulib module time_rz | 1640 | ## begin gnulib module time_rz |
| 1641 | 1641 | ||
| 1642 | 1642 | ||
| 1643 | EXTRA_DIST += time_rz.c | 1643 | EXTRA_DIST += time-internal.h time_rz.c |
| 1644 | 1644 | ||
| 1645 | EXTRA_libgnu_a_SOURCES += time_rz.c | 1645 | EXTRA_libgnu_a_SOURCES += time_rz.c |
| 1646 | 1646 | ||
diff --git a/lib/strftime.c b/lib/strftime.c index c7cec2621c9..d1ca346b687 100644 --- a/lib/strftime.c +++ b/lib/strftime.c | |||
| @@ -30,6 +30,7 @@ | |||
| 30 | # else | 30 | # else |
| 31 | # include "strftime.h" | 31 | # include "strftime.h" |
| 32 | # endif | 32 | # endif |
| 33 | # include "time-internal.h" | ||
| 33 | #endif | 34 | #endif |
| 34 | 35 | ||
| 35 | #include <ctype.h> | 36 | #include <ctype.h> |
| @@ -440,6 +441,9 @@ strftime_case_ (bool upcase, STREAM_OR_CHAR_T *s, | |||
| 440 | # define am_len STRLEN (a_month) | 441 | # define am_len STRLEN (a_month) |
| 441 | # define ap_len STRLEN (ampm) | 442 | # define ap_len STRLEN (ampm) |
| 442 | #endif | 443 | #endif |
| 444 | #if HAVE_TZNAME | ||
| 445 | char **tzname_vec = tzname; | ||
| 446 | #endif | ||
| 443 | const char *zone; | 447 | const char *zone; |
| 444 | size_t i = 0; | 448 | size_t i = 0; |
| 445 | STREAM_OR_CHAR_T *p = s; | 449 | STREAM_OR_CHAR_T *p = s; |
| @@ -475,6 +479,10 @@ strftime_case_ (bool upcase, STREAM_OR_CHAR_T *s, | |||
| 475 | } | 479 | } |
| 476 | else | 480 | else |
| 477 | { | 481 | { |
| 482 | # if !HAVE_TM_ZONE | ||
| 483 | /* Infer the zone name from *TZ instead of from TZNAME. */ | ||
| 484 | tzname_vec = tz->tzname_copy; | ||
| 485 | # endif | ||
| 478 | /* POSIX.1 requires that local time zone information be used as | 486 | /* POSIX.1 requires that local time zone information be used as |
| 479 | though strftime called tzset. */ | 487 | though strftime called tzset. */ |
| 480 | # if HAVE_TZSET | 488 | # if HAVE_TZSET |
| @@ -483,7 +491,7 @@ strftime_case_ (bool upcase, STREAM_OR_CHAR_T *s, | |||
| 483 | } | 491 | } |
| 484 | /* The tzset() call might have changed the value. */ | 492 | /* The tzset() call might have changed the value. */ |
| 485 | if (!(zone && *zone) && tp->tm_isdst >= 0) | 493 | if (!(zone && *zone) && tp->tm_isdst >= 0) |
| 486 | zone = tzname[tp->tm_isdst != 0]; | 494 | zone = tzname_vec[tp->tm_isdst != 0]; |
| 487 | #endif | 495 | #endif |
| 488 | if (! zone) | 496 | if (! zone) |
| 489 | zone = ""; | 497 | zone = ""; |
diff --git a/lib/time-internal.h b/lib/time-internal.h new file mode 100644 index 00000000000..6bf3f8d30b7 --- /dev/null +++ b/lib/time-internal.h | |||
| @@ -0,0 +1,49 @@ | |||
| 1 | /* Time internal interface | ||
| 2 | |||
| 3 | Copyright 2015 Free Software Foundation, Inc. | ||
| 4 | |||
| 5 | This program is free software; you can redistribute it and/or modify | ||
| 6 | it under the terms of the GNU General Public License as published by | ||
| 7 | the Free Software Foundation; either version 3, or (at your option) | ||
| 8 | any later version. | ||
| 9 | |||
| 10 | This program is distributed in the hope that it will be useful, | ||
| 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 13 | GNU General Public License for more details. | ||
| 14 | |||
| 15 | You should have received a copy of the GNU General Public License along | ||
| 16 | with this program; if not, see <http://www.gnu.org/licenses/>. */ | ||
| 17 | |||
| 18 | /* Written by Paul Eggert. */ | ||
| 19 | |||
| 20 | /* A time zone rule. */ | ||
| 21 | struct tm_zone | ||
| 22 | { | ||
| 23 | /* More abbreviations, should they be needed. Their TZ_IS_SET | ||
| 24 | members are zero. */ | ||
| 25 | struct tm_zone *next; | ||
| 26 | |||
| 27 | #if HAVE_TZNAME && !HAVE_TM_ZONE | ||
| 28 | /* Copies of recent strings taken from tzname[0] and tzname[1]. | ||
| 29 | The copies are in ABBRS, so that they survive tzset. Null if unknown. */ | ||
| 30 | char *tzname_copy[2]; | ||
| 31 | #endif | ||
| 32 | |||
| 33 | /* If nonzero, the rule represents the TZ environment variable set | ||
| 34 | to the first "abbreviation" (this may be the empty string). | ||
| 35 | Otherwise, it represents an unset TZ. */ | ||
| 36 | char tz_is_set; | ||
| 37 | |||
| 38 | /* A sequence of null-terminated strings packed next to each other. | ||
| 39 | The strings are followed by an extra null byte. If TZ_IS_SET, | ||
| 40 | there must be at least one string and the first string (which is | ||
| 41 | actually a TZ environment value value) may be empty. Otherwise | ||
| 42 | all strings must be nonempty. | ||
| 43 | |||
| 44 | Abbreviations are stored here because otherwise the values of | ||
| 45 | tm_zone and/or tzname would be dead after changing TZ and calling | ||
| 46 | tzset. Abbreviations never move once allocated, and are live | ||
| 47 | until tzfree is called. */ | ||
| 48 | char abbrs[FLEXIBLE_ARRAY_MEMBER]; | ||
| 49 | }; | ||
diff --git a/lib/time.in.h b/lib/time.in.h index 1adfe925398..a90552ce447 100644 --- a/lib/time.in.h +++ b/lib/time.in.h | |||
| @@ -22,13 +22,13 @@ | |||
| 22 | 22 | ||
| 23 | /* Don't get in the way of glibc when it includes time.h merely to | 23 | /* Don't get in the way of glibc when it includes time.h merely to |
| 24 | declare a few standard symbols, rather than to declare all the | 24 | declare a few standard symbols, rather than to declare all the |
| 25 | symbols. Also, Solaris 8 <time.h> eventually includes itself | 25 | symbols. (However, skip this for MinGW as it treats __need_time_t |
| 26 | incompatibly.) Also, Solaris 8 <time.h> eventually includes itself | ||
| 26 | recursively; if that is happening, just include the system <time.h> | 27 | recursively; if that is happening, just include the system <time.h> |
| 27 | without adding our own declarations. MinGW system headers use | 28 | without adding our own declarations. */ |
| 28 | these symbols as well, but we don't want to exclude MinGW from the | 29 | #if (((defined __need_time_t || defined __need_clock_t \ |
| 29 | 'else' branch below. */ | 30 | || defined __need_timespec) \ |
| 30 | #if (((defined __need_time_t || defined __need_clock_t \ | 31 | && !defined __MINGW32__) \ |
| 31 | || defined __need_timespec) && !defined __MINGW32__) \ | ||
| 32 | || defined _@GUARD_PREFIX@_TIME_H) | 32 | || defined _@GUARD_PREFIX@_TIME_H) |
| 33 | 33 | ||
| 34 | # @INCLUDE_NEXT@ @NEXT_TIME_H@ | 34 | # @INCLUDE_NEXT@ @NEXT_TIME_H@ |
diff --git a/lib/time_rz.c b/lib/time_rz.c index 8a4d7d13a2c..cbbe2c6ac2f 100644 --- a/lib/time_rz.c +++ b/lib/time_rz.c | |||
| @@ -32,35 +32,12 @@ | |||
| 32 | #include <stdlib.h> | 32 | #include <stdlib.h> |
| 33 | #include <string.h> | 33 | #include <string.h> |
| 34 | 34 | ||
| 35 | #include "time-internal.h" | ||
| 36 | |||
| 35 | #if !HAVE_TZSET | 37 | #if !HAVE_TZSET |
| 36 | static void tzset (void) { } | 38 | static void tzset (void) { } |
| 37 | #endif | 39 | #endif |
| 38 | 40 | ||
| 39 | /* A time zone rule. */ | ||
| 40 | struct tm_zone | ||
| 41 | { | ||
| 42 | /* More abbreviations, should they be needed. Their TZ_IS_SET | ||
| 43 | members are zero. */ | ||
| 44 | timezone_t next; | ||
| 45 | |||
| 46 | /* If nonzero, the rule represents the TZ environment variable set | ||
| 47 | to the first "abbreviation" (this may be the empty string). | ||
| 48 | Otherwise, it represents an unset TZ. */ | ||
| 49 | char tz_is_set; | ||
| 50 | |||
| 51 | /* A sequence of null-terminated strings packed next to each other. | ||
| 52 | The strings are followed by an extra null byte. If TZ_IS_SET, | ||
| 53 | there must be at least one string and the first string (which is | ||
| 54 | actually a TZ environment value value) may be empty. Otherwise | ||
| 55 | all strings must be nonempty. | ||
| 56 | |||
| 57 | Abbreviations are stored here because otherwise the values of | ||
| 58 | tm_zone and/or tzname would be dead after changing TZ and calling | ||
| 59 | tzset. Abbreviations never move once allocated, and are live | ||
| 60 | until tzfree is called. */ | ||
| 61 | char abbrs[FLEXIBLE_ARRAY_MEMBER]; | ||
| 62 | }; | ||
| 63 | |||
| 64 | /* The approximate size to use for small allocation requests. This is | 41 | /* The approximate size to use for small allocation requests. This is |
| 65 | the largest "small" request for the GNU C library malloc. */ | 42 | the largest "small" request for the GNU C library malloc. */ |
| 66 | enum { DEFAULT_MXFAST = 64 * sizeof (size_t) / 4 }; | 43 | enum { DEFAULT_MXFAST = 64 * sizeof (size_t) / 4 }; |
| @@ -124,39 +101,40 @@ tzalloc (char const *name) | |||
| 124 | if (tz) | 101 | if (tz) |
| 125 | { | 102 | { |
| 126 | tz->next = NULL; | 103 | tz->next = NULL; |
| 104 | #if HAVE_TZNAME && !HAVE_TM_ZONE | ||
| 105 | tz->tzname_copy[0] = tz->tzname_copy[1] = NULL; | ||
| 106 | #endif | ||
| 127 | tz->tz_is_set = !!name; | 107 | tz->tz_is_set = !!name; |
| 128 | extend_abbrs (tz->abbrs, name, name_size); | 108 | extend_abbrs (tz->abbrs, name, name_size); |
| 129 | } | 109 | } |
| 130 | return tz; | 110 | return tz; |
| 131 | } | 111 | } |
| 132 | 112 | ||
| 133 | #if HAVE_TZNAME | 113 | /* Save into TZ any nontrivial time zone abbreviation used by TM, and |
| 134 | /* If TZNAME_ADDRESS is nonnull, an assignment of a saved abbreviation. | 114 | update *TM (if HAVE_TM_ZONE) or *TZ (if !HAVE_TM_ZONE && |
| 135 | TZNAME_ADDRESS should be either null, or &tzname[0], or &tzname[1]. | 115 | HAVE_TZNAME) if they use the abbreviation. Return true if |
| 136 | *TZNAME_ADDRESS = TZNAME_VALUE should be done after revert_tz | 116 | successful, false (setting errno) otherwise. */ |
| 137 | (indirectly) calls tzset, so that revert_tz can overwrite tzset's | ||
| 138 | assignment to tzname. Also, it should be done at the start of | ||
| 139 | the next localtime_tz or mktime_z, to undo the overwrite. */ | ||
| 140 | static char **tzname_address; | ||
| 141 | static char *tzname_value; | ||
| 142 | #endif | ||
| 143 | |||
| 144 | /* Save into TZ any nontrivial time zone abbreviation used by TM, | ||
| 145 | and update *TM (or prepare to update tzname) if they use the abbreviation. | ||
| 146 | Return true if successful, false (setting errno) otherwise. */ | ||
| 147 | static bool | 117 | static bool |
| 148 | save_abbr (timezone_t tz, struct tm *tm) | 118 | save_abbr (timezone_t tz, struct tm *tm) |
| 149 | { | 119 | { |
| 150 | #if HAVE_TM_ZONE || HAVE_TZNAME | 120 | #if HAVE_TM_ZONE || HAVE_TZNAME |
| 151 | char const *zone = NULL; | 121 | char const *zone = NULL; |
| 152 | char **tzname_zone = NULL; | ||
| 153 | char *zone_copy = (char *) ""; | 122 | char *zone_copy = (char *) ""; |
| 123 | |||
| 124 | # if HAVE_TZNAME | ||
| 125 | int tzname_index = -1; | ||
| 126 | # endif | ||
| 127 | |||
| 154 | # if HAVE_TM_ZONE | 128 | # if HAVE_TM_ZONE |
| 155 | zone = tm->tm_zone; | 129 | zone = tm->tm_zone; |
| 156 | # endif | 130 | # endif |
| 131 | |||
| 157 | # if HAVE_TZNAME | 132 | # if HAVE_TZNAME |
| 158 | if (! (zone && *zone) && 0 <= tm->tm_isdst) | 133 | if (! (zone && *zone) && 0 <= tm->tm_isdst) |
| 159 | zone = *(tzname_zone = &tzname[0 < tm->tm_isdst]); | 134 | { |
| 135 | tzname_index = tm->tm_isdst != 0; | ||
| 136 | zone = tzname[tzname_index]; | ||
| 137 | } | ||
| 160 | # endif | 138 | # endif |
| 161 | 139 | ||
| 162 | /* No need to replace null zones, or zones within the struct tm. */ | 140 | /* No need to replace null zones, or zones within the struct tm. */ |
| @@ -196,14 +174,13 @@ save_abbr (timezone_t tz, struct tm *tm) | |||
| 196 | 174 | ||
| 197 | /* Replace the zone name so that its lifetime matches that of TZ. */ | 175 | /* Replace the zone name so that its lifetime matches that of TZ. */ |
| 198 | # if HAVE_TM_ZONE | 176 | # if HAVE_TM_ZONE |
| 199 | if (!tzname_zone) | 177 | tm->tm_zone = zone_copy; |
| 200 | tm->tm_zone = zone_copy; | 178 | # else |
| 201 | # endif | 179 | if (0 <= tzname_index) |
| 202 | # if HAVE_TZNAME | 180 | tz->tzname_copy[tzname_index] = zone_copy; |
| 203 | tzname_address = tzname_zone; | ||
| 204 | tzname_value = zone_copy; | ||
| 205 | # endif | 181 | # endif |
| 206 | #endif | 182 | #endif |
| 183 | |||
| 207 | return true; | 184 | return true; |
| 208 | } | 185 | } |
| 209 | 186 | ||
| @@ -292,41 +269,16 @@ revert_tz (timezone_t tz) | |||
| 292 | bool ok = change_env (tz); | 269 | bool ok = change_env (tz); |
| 293 | if (!ok) | 270 | if (!ok) |
| 294 | saved_errno = errno; | 271 | saved_errno = errno; |
| 295 | #if HAVE_TZNAME | ||
| 296 | if (!ok) | ||
| 297 | tzname_address = NULL; | ||
| 298 | if (tzname_address) | ||
| 299 | { | ||
| 300 | char *old_value = *tzname_address; | ||
| 301 | *tzname_address = tzname_value; | ||
| 302 | tzname_value = old_value; | ||
| 303 | } | ||
| 304 | #endif | ||
| 305 | tzfree (tz); | 272 | tzfree (tz); |
| 306 | errno = saved_errno; | 273 | errno = saved_errno; |
| 307 | return ok; | 274 | return ok; |
| 308 | } | 275 | } |
| 309 | } | 276 | } |
| 310 | 277 | ||
| 311 | /* Restore an old tzname setting that was temporarily munged by revert_tz. */ | ||
| 312 | static void | ||
| 313 | restore_tzname (void) | ||
| 314 | { | ||
| 315 | #if HAVE_TZNAME | ||
| 316 | if (tzname_address) | ||
| 317 | { | ||
| 318 | *tzname_address = tzname_value; | ||
| 319 | tzname_address = NULL; | ||
| 320 | } | ||
| 321 | #endif | ||
| 322 | } | ||
| 323 | |||
| 324 | /* Use time zone TZ to compute localtime_r (T, TM). */ | 278 | /* Use time zone TZ to compute localtime_r (T, TM). */ |
| 325 | struct tm * | 279 | struct tm * |
| 326 | localtime_rz (timezone_t tz, time_t const *t, struct tm *tm) | 280 | localtime_rz (timezone_t tz, time_t const *t, struct tm *tm) |
| 327 | { | 281 | { |
| 328 | restore_tzname (); | ||
| 329 | |||
| 330 | if (!tz) | 282 | if (!tz) |
| 331 | return gmtime_r (t, tm); | 283 | return gmtime_r (t, tm); |
| 332 | else | 284 | else |
| @@ -348,8 +300,6 @@ localtime_rz (timezone_t tz, time_t const *t, struct tm *tm) | |||
| 348 | time_t | 300 | time_t |
| 349 | mktime_z (timezone_t tz, struct tm *tm) | 301 | mktime_z (timezone_t tz, struct tm *tm) |
| 350 | { | 302 | { |
| 351 | restore_tzname (); | ||
| 352 | |||
| 353 | if (!tz) | 303 | if (!tz) |
| 354 | return timegm (tm); | 304 | return timegm (tm); |
| 355 | else | 305 | else |