[PROPOSED 1/3] Alias asctime, ctime result

I misread C99, and in a 2022-11-30 patch caused asctime and ctime to return different pointers when !SUPPORT_C89. However, C99 and later still require that these two functions return the same pointers, so revert that part of the 2022-11-30 change. * asctime.c (buf_ctime): Remove. All uses replaced with buf_asctime. --- asctime.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/asctime.c b/asctime.c index 1bfcafe9..491d23bf 100644 --- a/asctime.c +++ b/asctime.c @@ -30,16 +30,6 @@ 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 - /* On pre-C99 platforms, a snprintf substitute good enough for us. */ #if !HAVE_SNPRINTF # include <stdarg.h> @@ -86,8 +76,7 @@ asctime_r(struct tm const *restrict timeptr, char *restrict buf) register const char * mn; int year, mday, hour, min, sec; long long_TM_YEAR_BASE = TM_YEAR_BASE; - size_t bufsize = ((buf == buf_ctime - || (!SUPPORT_C89 && buf == buf_asctime)) + size_t bufsize = (buf == buf_asctime ? sizeof buf_asctime : STD_ASCTIME_BUF_SIZE); if (timeptr == NULL) { -- 2.47.1

* zic.c (xmalloc, xrealloc, xstrdup): Rename from emalloc, erealloc, estrdup. All uses changed. This ports better to NetBSD, which uses emalloc etc. for other purposes. --- zic.c | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/zic.c b/zic.c index 36199934..8a7f83db 100644 --- a/zic.c +++ b/zic.c @@ -524,19 +524,19 @@ memcheck(void *ptr) } static void * -emalloc(size_t size) +xmalloc(size_t size) { return memcheck(malloc(size)); } static void * -erealloc(void *ptr, size_t size) +xrealloc(void *ptr, size_t size) { return memcheck(realloc(ptr, size)); } static char * -estrdup(char const *str) +xstrdup(char const *str) { return memcheck(strdup(str)); } @@ -565,7 +565,7 @@ growalloc(void *ptr, ptrdiff_t itemsize, ptrdiff_t nitems, { return (nitems < *nitems_alloc ? ptr - : erealloc(ptr, grow_nitems_alloc(nitems_alloc, itemsize))); + : xrealloc(ptr, grow_nitems_alloc(nitems_alloc, itemsize))); } /* @@ -1321,7 +1321,7 @@ random_dirent(char const **name, char **namealloc) uint_fast64_t unfair_min = - ((UINTMAX_MAX % base__6 + 1) % base__6); if (!dst) { - dst = emalloc(size_sum(dirlen, prefixlen + suffixlen + 1)); + dst = xmalloc(size_sum(dirlen, prefixlen + suffixlen + 1)); memcpy(dst, src, dirlen); memcpy(dst + dirlen, prefix, prefixlen); dst[dirlen + prefixlen + suffixlen] = '\0'; @@ -1410,7 +1410,7 @@ relname(char const *target, char const *linkname) size_t lenslash = len + (len && directory[len - 1] != '/'); size_t targetsize = strlen(target) + 1; linksize = size_sum(lenslash, targetsize); - f = result = emalloc(linksize); + f = result = xmalloc(linksize); memcpy(result, directory, len); result[len] = '/'; memcpy(result + lenslash, target, targetsize); @@ -1424,7 +1424,7 @@ relname(char const *target, char const *linkname) dotdotetcsize = size_sum(size_product(dotdots, 3), taillen + 1); if (dotdotetcsize <= linksize) { if (!result) - result = emalloc(dotdotetcsize); + result = xmalloc(dotdotetcsize); for (i = 0; i < dotdots; i++) memcpy(result + 3 * i, "../", 3); memmove(result + 3 * dotdots, f + dir_len, taillen + 1); @@ -1866,8 +1866,8 @@ inrule(char **fields, int nfields) fields[RF_COMMAND], fields[RF_MONTH], fields[RF_DAY], fields[RF_TOD])) return; - r.r_name = estrdup(fields[RF_NAME]); - r.r_abbrvar = estrdup(fields[RF_ABBRVAR]); + r.r_name = xstrdup(fields[RF_NAME]); + r.r_abbrvar = xstrdup(fields[RF_ABBRVAR]); if (max_abbrvar_len < strlen(r.r_abbrvar)) max_abbrvar_len = strlen(r.r_abbrvar); rules = growalloc(rules, sizeof *rules, nrules, &nrules_alloc); @@ -1989,9 +1989,9 @@ inzsub(char **fields, int nfields, bool iscont) return false; } } - z.z_name = iscont ? NULL : estrdup(fields[ZF_NAME]); - z.z_rule = estrdup(fields[i_rule]); - z.z_format = cp1 = estrdup(fields[i_format]); + z.z_name = iscont ? NULL : xstrdup(fields[ZF_NAME]); + z.z_rule = xstrdup(fields[i_rule]); + z.z_format = cp1 = xstrdup(fields[i_format]); if (z.z_format_specifier == 'z') { cp1[cp - fields[i_format]] = 's'; if (noise) @@ -2134,8 +2134,8 @@ inlink(char **fields, int nfields) return; l.l_filenum = filenum; l.l_linenum = linenum; - l.l_target = estrdup(fields[LF_TARGET]); - l.l_linkname = estrdup(fields[LF_LINKNAME]); + l.l_target = xstrdup(fields[LF_TARGET]); + l.l_linkname = xstrdup(fields[LF_LINKNAME]); links = growalloc(links, sizeof *links, nlinks, &nlinks_alloc); links[nlinks++] = l; } @@ -2158,7 +2158,7 @@ rulesub(struct rule *rp, const char *loyearp, const char *hiyearp, rp->r_month = lp->l_value; rp->r_todisstd = false; rp->r_todisut = false; - dp = estrdup(timep); + dp = xstrdup(timep); if (*dp != '\0') { ep = dp + strlen(dp) - 1; switch (lowerit(*ep)) { @@ -2233,7 +2233,7 @@ rulesub(struct rule *rp, const char *loyearp, const char *hiyearp, ** Sun<=20 ** Sun>=7 */ - dp = estrdup(dayp); + dp = xstrdup(dayp); if ((lp = byword(dp, lasts)) != NULL) { rp->r_dycode = DC_DOWLEQ; rp->r_wday = lp->l_value; @@ -2391,7 +2391,7 @@ writezone(const char *const name, const char *const string, char version, /* Allocate the ATS and TYPES arrays via a single malloc, as this is a bit faster. Do not malloc(0) if !timecnt, as that might return NULL even on success. */ - zic_t *ats = emalloc(align_to(size_product(timecnt + !timecnt, + zic_t *ats = xmalloc(align_to(size_product(timecnt + !timecnt, sizeof *ats + 1), alignof(zic_t))); void *typesptr = ats + timecnt; @@ -3140,9 +3140,9 @@ outzone(const struct zone *zpfirst, ptrdiff_t zonecount) max_abbr_len = 2 + max_format_len + max_abbrvar_len; max_envvar_len = 2 * max_abbr_len + 5 * 9; - startbuf = emalloc(max_abbr_len + 1); - ab = emalloc(max_abbr_len + 1); - envvar = emalloc(max_envvar_len + 1); + startbuf = xmalloc(max_abbr_len + 1); + ab = xmalloc(max_abbr_len + 1); + envvar = xmalloc(max_envvar_len + 1); INITIALIZE(untiltime); INITIALIZE(starttime); /* @@ -3917,7 +3917,7 @@ mp = _("time zone abbreviation differs from POSIX standard"); static void mkdirs(char const *argname, bool ancestors) { - char *name = estrdup(argname); + char *name = xstrdup(argname); char *cp = name; /* On MS-Windows systems, do not worry about drive letters or -- 2.47.1

NetBSD enables -Wcast-qual when building its localtime.c. * Makefile (GCC_DEBUG_FLAGS): Add -Wcast-qual. * localtime.c (TYPECVT, UNCONST): New macros. (tzname) [2 <= HAVE_TZNAME + TZ_TIME_T]: (update_tzname_etc, settzname, localsub, gmtsub): Use UNCONST instead of casting to char *. --- Makefile | 3 ++- localtime.c | 31 ++++++++++++++++++++++--------- 2 files changed, 24 insertions(+), 10 deletions(-) diff --git a/Makefile b/Makefile index f1ce7abb..2130582c 100644 --- a/Makefile +++ b/Makefile @@ -320,7 +320,8 @@ GCC_DEBUG_FLAGS = -DGCC_LINT -g3 -O3 \ $(GCC_INSTRUMENT) \ -Wall -Wextra \ -Walloc-size-larger-than=100000 -Warray-bounds=2 \ - -Wbad-function-cast -Wbidi-chars=any,ucn -Wcast-align=strict -Wdate-time \ + -Wbad-function-cast -Wbidi-chars=any,ucn -Wcast-align=strict -Wcast-qual \ + -Wdate-time \ -Wdeclaration-after-statement -Wdouble-promotion \ -Wduplicated-branches -Wduplicated-cond -Wflex-array-member-not-at-end \ -Wformat=2 -Wformat-overflow=2 -Wformat-signedness -Wformat-truncation \ diff --git a/localtime.c b/localtime.c index 441c5edd..9c185e66 100644 --- a/localtime.c +++ b/localtime.c @@ -37,6 +37,22 @@ static int lock(void) { return 0; } static void unlock(void) { } #endif +/* Convert to TYPE the value of the expression EXPR. Use C99+ implicit + conversion if available, as it is less powerful and therefore safer. */ +#if PORT_TO_C89 +# define TYPECVT(type, expr) ((type) (expr)) +#else +# define TYPECVT(type, expr) ((type) {expr}) +#endif + +/* Unless intptr_t is missing, pacify gcc -Wcast-qual on char const * exprs. + This is a macro so that it can be used in static initializers. */ +#ifdef INTPTR_MAX +# define UNCONST(a) ((char *) (intptr_t) TYPECVT (char const *, a)) +#else +# define UNCONST(a) TYPECVT (char const *, a) +#endif + /* A signed type wider than int, so that we can add 1900 + tm_mon/12 to tm_year without overflow. The static_assert checks that it is indeed wider than int; if this fails on your platform please let us know. */ @@ -290,10 +306,7 @@ static struct tm tm; #endif # if 2 <= HAVE_TZNAME + TZ_TIME_T -char * tzname[2] = { - (char *) wildabbr, - (char *) wildabbr -}; +char *tzname[2] = { UNCONST(wildabbr), UNCONST(wildabbr) }; # endif # if 2 <= USG_COMPAT + TZ_TIME_T long timezone; @@ -378,7 +391,7 @@ static void update_tzname_etc(struct state const *sp, struct ttinfo const *ttisp) { # if HAVE_TZNAME - tzname[ttisp->tt_isdst] = (char *) &sp->chars[ttisp->tt_desigidx]; + tzname[ttisp->tt_isdst] = UNCONST(&sp->chars[ttisp->tt_desigidx]); # endif # if USG_COMPAT if (!ttisp->tt_isdst) @@ -419,7 +432,7 @@ settzname(void) int stddst_mask = 0; # if HAVE_TZNAME - tzname[0] = tzname[1] = (char *) (sp ? wildabbr : utc); + tzname[0] = tzname[1] = UNCONST(sp ? wildabbr : utc); stddst_mask = 3; # endif # if USG_COMPAT @@ -1657,7 +1670,7 @@ localsub(struct state const *sp, time_t const *timep, int_fast32_t setname, if (result) { result->tm_isdst = ttisp->tt_isdst; # ifdef TM_ZONE - result->TM_ZONE = (char *) &sp->chars[ttisp->tt_desigidx]; + result->TM_ZONE = UNCONST(&sp->chars[ttisp->tt_desigidx]); # endif if (setname) update_tzname_etc(sp, ttisp); @@ -1725,8 +1738,8 @@ gmtsub(ATTRIBUTE_MAYBE_UNUSED struct state const *sp, time_t const *timep, ** "+xx" or "-xx" if offset is non-zero, ** but this is no time for a treasure hunt. */ - tmp->TM_ZONE = ((char *) - (offset ? wildabbr : gmtptr ? gmtptr->chars : utc)); + tmp->TM_ZONE = UNCONST(offset ? wildabbr + : gmtptr ? gmtptr->chars : utc); #endif /* defined TM_ZONE */ return result; } -- 2.47.1
participants (1)
-
Paul Eggert