diff options
Diffstat (limited to 'tz/zdump.c')
-rw-r--r-- | tz/zdump.c | 48 |
1 files changed, 40 insertions, 8 deletions
@@ -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 |