[tz] [PATCH] zdump ports better to odd C11 platforms
Paul Eggert
eggert at cs.ucla.edu
Tue Jan 25 19:13:35 UTC 2022
* zdump.c (HAVE_GENERIC): Define if not already defined,
with the same definiens as private.h.
(tformat): Prefer _Generic if it works, as this is more reliable
than guessing via sizeof.
---
zdump.c | 38 +++++++++++++++++++++++++++++++++++++-
1 file changed, 37 insertions(+), 1 deletion(-)
diff --git a/zdump.c b/zdump.c
index f08afbd..79ff1fd 100644
--- a/zdump.c
+++ b/zdump.c
@@ -56,6 +56,21 @@
*/
enum { SECSPER400YEARS_FITS = SECSPERLYEAR <= INTMAX_MAX / 400 };
+#if !defined HAVE_GENERIC && defined __has_extension
+# if __has_extension(c_generic_selections)
+# define HAVE_GENERIC 1
+# else
+# define HAVE_GENERIC 0
+# endif
+#endif
+/* _Generic is buggy in pre-4.9 GCC. */
+#if !defined HAVE_GENERIC && defined __GNUC__
+# define HAVE_GENERIC (4 < __GNUC__ + (9 <= __GNUC_MINOR__))
+#endif
+#ifndef HAVE_GENERIC
+# define HAVE_GENERIC (201112 <= __STDC_VERSION__)
+#endif
+
#if HAVE_GETTEXT
#include <locale.h> /* for setlocale */
#endif /* HAVE_GETTEXT */
@@ -1123,12 +1138,33 @@ abbr(struct tm const *tmp)
/*
** The code below can fail on certain theoretical systems;
-** it works on all known real-world systems as of 2004-12-30.
+** it works on all known real-world systems as of 2021-01-25.
*/
static const char *
tformat(void)
{
+#if HAVE_GENERIC
+ /* C11-style _Generic is more likely to return the correct
+ format when distinct types have the same size. */
+ char const *fmt =
+ _Generic((time_t) 0,
+ signed char: "%d", short: "%d", int: "%d",
+ long: "%ld", long long: "%lld",
+ char: CHAR_MAX <= INT_MAX ? "%d" : "%u",
+ unsigned char: UCHAR_MAX <= INT_MAX ? "%d" : "%u",
+ unsigned short: USHRT_MAX <= INT_MAX ? "%d" : "%u",
+ unsigned: "%u", unsigned long: "%lu",
+ unsigned long long: "%llu",
+ default: NULL);
+ if (fmt)
+ return fmt;
+ fmt = _Generic((time_t) 0,
+ intmax_t: "%"PRIdMAX, uintmax_t: "%"PRIuMAX,
+ default: NULL);
+ if (fmt)
+ return fmt;
+#endif
if (0 > (time_t) -1) { /* signed */
if (sizeof(time_t) == sizeof(intmax_t))
return "%"PRIdMAX;
--
2.34.1
More information about the tz
mailing list