summaryrefslogtreecommitdiff
path: root/tz/zdump.c
diff options
context:
space:
mode:
Diffstat (limited to 'tz/zdump.c')
-rw-r--r--tz/zdump.c48
1 files changed, 40 insertions, 8 deletions
diff --git a/tz/zdump.c b/tz/zdump.c
index e198b04..8b6788a 100644
--- a/tz/zdump.c
+++ b/tz/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 */
@@ -131,7 +146,7 @@ sumsize(size_t a, size_t b)
{
size_t sum = a + b;
if (sum < a) {
- fprintf(stderr, "%s: size overflow\n", progname);
+ fprintf(stderr, _("%s: size overflow\n"), progname);
exit(EXIT_FAILURE);
}
return sum;
@@ -798,6 +813,7 @@ show(timezone_t tz, char *zone, time_t t, bool v)
gmtmp = my_gmtime_r(&t, &gmtm);
if (gmtmp == NULL) {
printf(tformat(), t);
+ printf(_(" (gmtime failed)"));
} else {
dumptime(gmtmp);
printf(" UT");
@@ -805,8 +821,11 @@ show(timezone_t tz, char *zone, time_t t, bool v)
printf(" = ");
}
tmp = my_localtime_rz(tz, &t, &tm);
- dumptime(tmp);
- if (tmp != NULL) {
+ if (tmp == NULL) {
+ printf(tformat(), t);
+ printf(_(" (localtime failed)"));
+ } else {
+ dumptime(tmp);
if (*abbr(tmp) != '\0')
printf(" %s", abbr(tmp));
if (v) {
@@ -1119,12 +1138,29 @@ 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 2022-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,
+ int: "%d", long: "%ld", long long: "%lld",
+ 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;
@@ -1158,10 +1194,6 @@ dumptime(register const struct tm *timeptr)
register int lead;
register int trail;
- if (timeptr == NULL) {
- printf("NULL");
- return;
- }
/*
** The packaged localtime_rz and gmtime_r never put out-of-range
** values in tm_wday or tm_mon, but since this code might be compiled