From cad62551c5fa9865dbe0841a0b3bc729c4fbe8fc Mon Sep 17 00:00:00 2001 From: Lasse Collin Date: Fri, 26 Jun 2009 20:36:45 +0300 Subject: Ugly hack to make it possible to use the thousand separator format character with snprintf() on POSIX systems but not on non-POSIX systems and still keep xgettext working. --- src/xz/message.c | 17 +++++++++-------- src/xz/process.c | 30 +++++++++++++++--------------- src/xz/util.c | 34 ++++++++++++++++++++++++++++++++++ src/xz/util.h | 20 ++++++++++++++++++++ 4 files changed, 78 insertions(+), 23 deletions(-) (limited to 'src') diff --git a/src/xz/message.c b/src/xz/message.c index 1d9cb76e..8fa06e15 100644 --- a/src/xz/message.c +++ b/src/xz/message.c @@ -363,21 +363,22 @@ progress_sizes_helper(char **pos, size_t *left, uint64_t value, bool final) if (final) { // At maximum of four digits is allowed for exact byte count. if (value < 10000) { - my_snprintf(pos, left, "%'" PRIu64 " B", value); + my_snprintf(pos, left, "%s B", + uint64_to_str(value, 0)); return; } // At maximum of five significant digits is allowed for KiB. if (value < UINT64_C(10239900)) { - my_snprintf(pos, left, "%'.1f KiB", - (double)(value) / 1024.0); + my_snprintf(pos, left, "%s KiB", double_to_str( + (double)(value) / 1024.0)); return; } } // Otherwise we use MiB. - my_snprintf(pos, left, "%'.1f MiB", - (double)(value) / (1024.0 * 1024.0)); + my_snprintf(pos, left, "%s MiB", + double_to_str((double)(value) / (1024.0 * 1024.0))); return; } @@ -1157,10 +1158,10 @@ message_help(bool long_help) if (long_help) { printf(_( "On this system and configuration, this program will use at maximum of roughly\n" -"%'" PRIu64 " MiB RAM and "), hardware_memlimit_get() / (1024 * 1024)); - printf(N_("one thread.\n\n", "%'" PRIu32 " threads.\n\n", +"%s MiB RAM and "), uint64_to_str(hardware_memlimit_get() / (1024 * 1024), 0)); + printf(N_("one thread.\n\n", "%s threads.\n\n", hardware_threadlimit_get()), - hardware_threadlimit_get()); + uint64_to_str(hardware_threadlimit_get(), 0)); } printf(_("Report bugs to <%s> (in English or Finnish).\n"), diff --git a/src/xz/process.c b/src/xz/process.c index 7a3c4149..0731ad94 100644 --- a/src/xz/process.c +++ b/src/xz/process.c @@ -163,11 +163,12 @@ coder_set_compression_settings(void) message_fatal("Unsupported filter chain or filter options"); // Print memory usage info. - message(V_DEBUG, _("%'" PRIu64 " MiB (%'" PRIu64 " B) of memory is " - "required per thread, " - "limit is %'" PRIu64 " MiB (%'" PRIu64 " B)"), - memory_usage >> 20, memory_usage, - memory_limit >> 20, memory_limit); + message(V_DEBUG, _("%s MiB (%s B) of memory is required per thread, " + "limit is %s MiB (%s B)"), + uint64_to_str(memory_usage >> 20, 0), + uint64_to_str(memory_usage, 1), + uint64_to_str(memory_limit >> 20, 2), + uint64_to_str(memory_limit, 3)); if (memory_usage > memory_limit) { // If --no-auto-adjust was used or we didn't find LZMA1 or @@ -225,15 +226,13 @@ coder_set_compression_settings(void) // was given. FIXME: Always warn? if (!preset_default) message(V_WARNING, "Adjusted LZMA%c dictionary size " - "from %'" PRIu32 " MiB to " - "%'" PRIu32 " MiB to not exceed " - "the memory usage limit of " - "%'" PRIu64 " MiB", + "from %s MiB to %s MiB to not exceed " + "the memory usage limit of %s MiB", filters[i].id == LZMA_FILTER_LZMA2 ? '2' : '1', - orig_dict_size >> 20, - opt->dict_size >> 20, - memory_limit >> 20); + uint64_to_str(orig_dict_size >> 20, 0), + uint64_to_str(opt->dict_size >> 20, 1), + uint64_to_str(memory_limit >> 20, 2)); } /* @@ -443,10 +442,11 @@ coder_run(file_pair *pair) / (1024 * 1024); memlimit /= 1024 * 1024; - message_error(_("Limit was %'" PRIu64 " MiB, " - "but %'" PRIu64 " MiB would " + message_error(_("Limit was %s MiB, " + "but %s MiB would " "have been needed"), - memlimit, memusage); + uint64_to_str(memlimit, 0), + uint64_to_str(memusage, 1)); } if (stop) diff --git a/src/xz/util.c b/src/xz/util.c index d200bfca..d160ea0d 100644 --- a/src/xz/util.c +++ b/src/xz/util.c @@ -13,6 +13,15 @@ #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) { @@ -118,6 +127,31 @@ error: } +extern const char * +uint64_to_str(uint64_t value, uint32_t slot) +{ + // 2^64 with thousand separators is 26 bytes plus trailing '\0'. + static char bufs[4][32]; + + assert(slot < ARRAY_SIZE(bufs)); + + snprintf(bufs[slot], sizeof(bufs[slot]), "%" THOUSAND PRIu64, value); + return bufs[slot]; +} + + +extern const char * +double_to_str(double value) +{ + // 64 bytes is surely enough, since it won't fit in some other + // fields anyway. + static char buf[64]; + + snprintf(buf, sizeof(buf), "%" THOUSAND ".1f", value); + return buf; +} + + /* /// \brief Simple quoting to get rid of ASCII control characters /// diff --git a/src/xz/util.h b/src/xz/util.h index 511d2ee9..3657eb80 100644 --- a/src/xz/util.h +++ b/src/xz/util.h @@ -41,6 +41,26 @@ extern uint64_t str_to_uint64(const char *name, const char *value, uint64_t min, uint64_t max); +/// \brief Convert uint64_t to a string +/// +/// Convert the given value to a string with locale-specific thousand +/// separators, if supported by the snprintf() implementation. The string +/// is stored into an internal static buffer indicated by the slot argument. +/// A pointer to the selected buffer is returned. +/// +/// This function exists, because non-POSIX systems don't support thousand +/// separator in format strings. Solving the problem in a simple way doesn't +/// work, because it breaks gettext (specifically, the xgettext tool). +extern const char *uint64_to_str(uint64_t value, uint32_t slot); + + +/// \brief Convert double to a string with one decimal place +/// +/// This is like uint64_to_str() except that this converts a double and +/// uses exactly one decimal place. +extern const char *double_to_str(double value); + + /// \brief Check if filename is empty and print an error message extern bool is_empty_filename(const char *filename); -- cgit v1.2.3