From 94c66b3297b3ad307eee93cf6b160e3c43997f11 Mon Sep 17 00:00:00 2001 From: Lasse Collin Date: Sat, 29 Aug 2009 14:43:52 +0300 Subject: [PATCH] Use even more hackish way to support thousand separators. Seems that in addition on Windows and DOS, also OpenBSD lacks support for %'d style printf() format strings. So far that is the only modern POSIX-like system I know with this problem, but after this hack, the thousand separator shouldn't be a problem on any system. Maybe testing if a format string like %'d produces reasonable output is invoking undefined behavior on some systems, but so far all the problematic systems I've tried just print the raw format string (e.g. %'d prints 'd). Maybe Autoconf test would have been better, but this hack works also for cross-compilation, and avoids recompilation in case the system libc starts to support the thousand separator. --- src/xz/util.c | 36 +++++++++++++++++++++++++----------- 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/src/xz/util.c b/src/xz/util.c index d160ea0d..9f6bdddd 100644 --- a/src/xz/util.c +++ b/src/xz/util.c @@ -13,15 +13,6 @@ #include "private.h" -// Thousand separator for format strings is not supported outside POSIX. -// This is used in uint64_to_str() and double_to_str(). -#ifdef DOSLIKE -# define THOUSAND "" -#else -# define THOUSAND "'" -#endif - - extern void * xrealloc(void *ptr, size_t size) { @@ -135,7 +126,19 @@ uint64_to_str(uint64_t value, uint32_t slot) assert(slot < ARRAY_SIZE(bufs)); - snprintf(bufs[slot], sizeof(bufs[slot]), "%" THOUSAND PRIu64, value); + static enum { UNKNOWN, WORKS, BROKEN } thousand = UNKNOWN; + if (thousand == UNKNOWN) { + bufs[slot][0] = '\0'; + snprintf(bufs[slot], sizeof(bufs[slot]), "%'" PRIu64, + UINT64_C(1)); + thousand = bufs[slot][0] == '1' ? WORKS : BROKEN; + } + + if (thousand == WORKS) + snprintf(bufs[slot], sizeof(bufs[slot]), "%'" PRIu64, value); + else + snprintf(bufs[slot], sizeof(bufs[slot]), "%" PRIu64, value); + return bufs[slot]; } @@ -147,7 +150,18 @@ double_to_str(double value) // fields anyway. static char buf[64]; - snprintf(buf, sizeof(buf), "%" THOUSAND ".1f", value); + static enum { UNKNOWN, WORKS, BROKEN } thousand = UNKNOWN; + if (thousand == UNKNOWN) { + buf[0] = '\0'; + snprintf(buf, sizeof(buf), "%'.1f", 2.0); + thousand = buf[0] == '2' ? WORKS : BROKEN; + } + + if (thousand == WORKS) + snprintf(buf, sizeof(buf), "%'.1f", value); + else + snprintf(buf, sizeof(buf), "%.1f", value); + return buf; }