[PROPOSED 1/4] Always define STD_INSPIRED
* private.h (STD_INSPIRED): Default to 0. All uses changed. This is purely refactoring, so that STD_INSPIRED is more like other macros in this file. --- Makefile | 2 +- localtime.c | 10 +++++----- private.h | 7 +++++-- theory.html | 2 +- 4 files changed, 12 insertions(+), 9 deletions(-) diff --git a/Makefile b/Makefile index 2c09f94..f0cbf7f 100644 --- a/Makefile +++ b/Makefile @@ -363,7 +363,7 @@ GCC_DEBUG_FLAGS = -DGCC_LINT -g3 -O3 -fno-common \ # -DNETBSD_INSPIRED=0 # to the end of the "CFLAGS=" line. Otherwise, the functions # "localtime_rz", "mktime_z", "tzalloc", and "tzfree" are added to the -# time library, and if STD_INSPIRED is also defined the functions +# time library, and if STD_INSPIRED is also defined to nonzero the functions # "posix2time_z" and "time2posix_z" are added as well. # The functions ending in "_z" (or "_rz") are like their unsuffixed # (or suffixed-by-"_r") counterparts, except with an extra first diff --git a/localtime.c b/localtime.c index 1d22d35..462d054 100644 --- a/localtime.c +++ b/localtime.c @@ -1697,7 +1697,7 @@ gmtime(const time_t *timep) return gmtime_r(timep, &tm); } -#ifdef STD_INSPIRED +#if STD_INSPIRED struct tm * offtime(const time_t *timep, long offset) @@ -1706,7 +1706,7 @@ offtime(const time_t *timep, long offset) return gmtsub(gmtptr, timep, offset, &tm); } -#endif /* defined STD_INSPIRED */ +#endif /* ** Return the number of leap years through the end of the given year @@ -2325,7 +2325,7 @@ mktime(struct tm *tmp) return t; } -#ifdef STD_INSPIRED +#if STD_INSPIRED time_t timelocal(struct tm *tmp) { @@ -2377,7 +2377,7 @@ leapcorr(struct state const *sp, time_t t) ** XXX--is the below the right way to conditionalize?? */ -#ifdef STD_INSPIRED +#if STD_INSPIRED /* NETBSD_INSPIRED_EXTERN functions are exported to callers if NETBSD_INSPIRED is defined, and are private otherwise. */ @@ -2462,7 +2462,7 @@ posix2time(time_t t) return t; } -#endif /* defined STD_INSPIRED */ +#endif /* STD_INSPIRED */ #if TZ_TIME_T diff --git a/private.h b/private.h index 9cb9c24..b5fdf5a 100644 --- a/private.h +++ b/private.h @@ -691,7 +691,10 @@ extern long altzone; ** declarations if time_tz is defined. */ -#ifdef STD_INSPIRED +#ifndef STD_INSPIRED +# define STD_INSPIRED 0 +#endif +#if STD_INSPIRED # if TZ_TIME_T || !defined offtime struct tm *offtime(time_t const *, long); # endif @@ -738,7 +741,7 @@ struct tm *localtime_rz(timezone_t restrict, time_t const *restrict, time_t mktime_z(timezone_t restrict, struct tm *restrict); timezone_t tzalloc(char const *); void tzfree(timezone_t); -# ifdef STD_INSPIRED +# if STD_INSPIRED # if TZ_TIME_T || !defined posix2time_z time_t posix2time_z(timezone_t, time_t) ATTRIBUTE_REPRODUCIBLE; # endif diff --git a/theory.html b/theory.html index 75e347f..f2b798b 100644 --- a/theory.html +++ b/theory.html @@ -1173,7 +1173,7 @@ The vestigial <abbr>API</abbr>s are: </li> <li> The functions that are conditionally compiled - if <code>STD_INSPIRED</code> is defined should, at this point, be + if <code>STD_INSPIRED</code> is nonzero should, at this point, be looked on primarily as food for thought. They are not in any sense "standard compatible" – some are not, in fact, specified in <em>any</em> standard. -- 2.38.1
* asctime.c (ctime, ctime_r): Move here ... * localtime.c (ctime): ... from here, as it’s a bit better location and should help simplify future changes. --- asctime.c | 15 +++++++++++++++ localtime.c | 21 --------------------- 2 files changed, 15 insertions(+), 21 deletions(-) diff --git a/asctime.c b/asctime.c index f0159f8..c001621 100644 --- a/asctime.c +++ b/asctime.c @@ -104,3 +104,18 @@ asctime(register const struct tm *timeptr) { return asctime_r(timeptr, buf_asctime); } + +char * +ctime_r(const time_t *timep, char *buf) +{ + struct tm mytm; + struct tm *tmp = localtime_r(timep, &mytm); + return tmp ? asctime_r(tmp, buf) : NULL; +} + +char * +ctime(const time_t *timep) +{ + struct tm *tmp = localtime(timep); + return tmp ? asctime(tmp) : NULL; +} diff --git a/localtime.c b/localtime.c index 462d054..cb34a9e 100644 --- a/localtime.c +++ b/localtime.c @@ -1842,27 +1842,6 @@ timesub(const time_t *timep, int_fast32_t offset, return tmp; } -char * -ctime(const time_t *timep) -{ -/* -** Section 4.12.3.2 of X3.159-1989 requires that -** The ctime function converts the calendar time pointed to by timer -** to local time in the form of a string. It is equivalent to -** asctime(localtime(timer)) -*/ - struct tm *tmp = localtime(timep); - return tmp ? asctime(tmp) : NULL; -} - -char * -ctime_r(const time_t *timep, char *buf) -{ - struct tm mytm; - struct tm *tmp = localtime_r(timep, &mytm); - return tmp ? asctime_r(tmp, buf) : NULL; -} - /* ** Adapted from code provided by Robert Elz, who writes: ** The "best" way to do mktime I think is based on an idea of Bob -- 2.38.1
If C23, deprecate any substitutes for asctime and ctime, since C23 deprecates the originals. * private.h (ATTRIBUTE_DEPRECATED, DEPRECATED_IN_C23): New macros. Use the latter on asctime and ctime. --- private.h | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/private.h b/private.h index b5fdf5a..4a1f667 100644 --- a/private.h +++ b/private.h @@ -440,6 +440,19 @@ typedef unsigned long uintmax_t; # define HAVE___HAS_C_ATTRIBUTE false #endif +#if HAVE___HAS_C_ATTRIBUTE +# if __has_c_attribute(deprecated) +# define ATTRIBUTE_DEPRECATED [[deprecated]] +# endif +#endif +#ifndef ATTRIBUTE_DEPRECATED +# if 3 < __GNUC__ + (2 <= __GNUC_MINOR__) +# define ATTRIBUTE_DEPRECATED __attribute__((deprecated)) +# else +# define ATTRIBUTE_DEPRECATED /* empty */ +# endif +#endif + #if HAVE___HAS_C_ATTRIBUTE # if __has_c_attribute(fallthrough) # define ATTRIBUTE_FALLTHROUGH [[fallthrough]] @@ -624,9 +637,14 @@ typedef time_tz tz_time_t; # define altzone tz_altzone # endif -char *asctime(struct tm const *); +# if __STDC_VERSION__ < 202311 +# define DEPRECATED_IN_C23 /* empty */ +# else +# define DEPRECATED_IN_C23 ATTRIBUTE_DEPRECATED +# endif +DEPRECATED_IN_C23 char *asctime(struct tm const *); char *asctime_r(struct tm const *restrict, char *restrict); -char *ctime(time_t const *); +DEPRECATED_IN_C23 char *ctime(time_t const *); char *ctime_r(time_t const *, char *); double difftime(time_t, time_t) ATTRIBUTE_UNSEQUENCED; size_t strftime(char *restrict, size_t, char const *restrict, -- 2.38.1
C89 requires that localtime(...) == gmtime(...) when both are successful, and similarly for asctime(...) == ctime(...). This can lead to bugs in badly-written programs, so continue to support it only if compiling with -DSUPPORT_C89, since the requirement was removed in C99. * Makefile, NEWS: Mention this. * asctime.c (buf_ctime): New macro or (if !SUPPORT_C89) static variable. (asctime_r): Check for it. (ctime): Use it. * localtime.c (tm) [!SUPPORT_C89]: Use three instances of this variable instead of one. * private.h (SUPPORT_C89): Default to 0. --- Makefile | 2 ++ NEWS | 13 +++++++++++++ asctime.c | 16 +++++++++++++--- localtime.c | 15 +++++++++++++++ private.h | 4 ++++ 5 files changed, 47 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index f0cbf7f..63f3b5c 100644 --- a/Makefile +++ b/Makefile @@ -245,6 +245,8 @@ LDLIBS= # -DRESERVE_STD_EXT_IDS if your platform reserves standard identifiers # with external linkage, e.g., applications cannot define 'localtime'. # -Dssize_t=long on hosts like MS-Windows that lack ssize_t +# -DSUPPORT_C89 if you build or run tzcode on a C89 platform; this option +# is obsolescent and is planned to be removed when C99+ is required. # -DSUPPRESS_TZDIR to not prepend TZDIR to file names; this has # security implications and is not recommended for general use # -DTHREAD_SAFE to make localtime.c thread-safe, as POSIX requires; diff --git a/NEWS b/NEWS index 701e490..9cb175e 100644 --- a/NEWS +++ b/NEWS @@ -1,5 +1,18 @@ News for the tz database +Unreleased, experimental changes + + Briefly: + tzcode no longer supports C89 unless built with -DSUPPORT_C89 + + Changes to code + + tzcode no longer supports C89 by default. To build or run in a + C89 environment, compile with -DSUPPORT_C89, a transitional aid + that is planned to be removed in a near-future version, when C99 + or later will be required. + + Release 2022g - 2022-11-29 08:58:31 -0800 Briefly: diff --git a/asctime.c b/asctime.c index c001621..c84fe8c 100644 --- a/asctime.c +++ b/asctime.c @@ -50,6 +50,16 @@ enum { STD_ASCTIME_BUF_SIZE = 26 }; */ static char buf_asctime[2*3 + 5*INT_STRLEN_MAXIMUM(int) + 7 + 2 + 1 + 1]; +/* A similar buffer for ctime. + C89 requires that they be the same buffer. + This requirement was removed in C99, so support it only if requested, + as support is more likely to lead to bugs in badly-written programs. */ +#if SUPPORT_C89 +# define buf_ctime buf_asctime +#else +static char buf_ctime[sizeof buf_asctime]; +#endif + char * asctime_r(register const struct tm *timeptr, char *buf) { @@ -91,7 +101,8 @@ asctime_r(register const struct tm *timeptr, char *buf) timeptr->tm_mday, timeptr->tm_hour, timeptr->tm_min, timeptr->tm_sec, year); - if (strlen(result) < STD_ASCTIME_BUF_SIZE || buf == buf_asctime) + if (strlen(result) < STD_ASCTIME_BUF_SIZE + || buf == buf_ctime || buf == buf_asctime) return strcpy(buf, result); else { errno = EOVERFLOW; @@ -116,6 +127,5 @@ ctime_r(const time_t *timep, char *buf) char * ctime(const time_t *timep) { - struct tm *tmp = localtime(timep); - return tmp ? asctime(tmp) : NULL; + return ctime_r(timep, buf_ctime); } diff --git a/localtime.c b/localtime.c index cb34a9e..f8a0a6e 100644 --- a/localtime.c +++ b/localtime.c @@ -186,9 +186,14 @@ static int lcl_is_set; ** ctime, gmtime, localtime] return values in one of two static ** objects: a broken-down time structure and an array of char. ** Thanks to Paul Eggert for noting this. +** +** This requirement was removed in C99, so support it only if requested, +** as support is more likely to lead to bugs in badly-written programs. */ +#if SUPPORT_C89 static struct tm tm; +#endif #if 2 <= HAVE_TZNAME + TZ_TIME_T char * tzname[2] = { @@ -1648,6 +1653,9 @@ localtime_tzset(time_t const *timep, struct tm *tmp, bool setname) struct tm * localtime(const time_t *timep) { +#if !SUPPORT_C89 + static struct tm tm; +#endif return localtime_tzset(timep, &tm, true); } @@ -1694,6 +1702,9 @@ gmtime_r(const time_t *timep, struct tm *tmp) struct tm * gmtime(const time_t *timep) { +#if !SUPPORT_C89 + static struct tm tm; +#endif return gmtime_r(timep, &tm); } @@ -1703,6 +1714,10 @@ struct tm * offtime(const time_t *timep, long offset) { gmtcheck(); + +#if !SUPPORT_C89 + static struct tm tm; +#endif return gmtsub(gmtptr, timep, offset, &tm); } diff --git a/private.h b/private.h index 4a1f667..c22354a 100644 --- a/private.h +++ b/private.h @@ -704,6 +704,10 @@ extern int daylight; extern long altzone; #endif +#ifndef SUPPORT_C89 +# define SUPPORT_C89 0 +#endif + /* ** The STD_INSPIRED functions are similar, but most also need ** declarations if time_tz is defined. -- 2.38.1
participants (1)
-
Paul Eggert