Ugly hack to make it possible to use the thousand separator
authorLasse Collin <lasse.collin@tukaani.org>
Fri, 26 Jun 2009 17:36:45 +0000 (20:36 +0300)
committerLasse Collin <lasse.collin@tukaani.org>
Fri, 26 Jun 2009 17:36:45 +0000 (20:36 +0300)
format character with snprintf() on POSIX systems but not
on non-POSIX systems and still keep xgettext working.

dos/Makefile
src/xz/message.c
src/xz/process.c
src/xz/util.c
src/xz/util.h
windows/Makefile

index 67437cd..9d56312 100644 (file)
@@ -184,7 +184,7 @@ $(GETOPT_OBJS): %.o: %.c $(GETOPT_H)
 getopt.a: $(GETOPT_OBJS)
        $(RM) $@
        $(AR) rcs $@ $(GETOPT_OBJS)
-       $(STRIP) --strip-unneeded $@    
+       $(STRIP) --strip-unneeded $@
 
 getopt-clean:
        $(RM) $(GETOPT_H) $(GETOPT_OBJS) getopt.a
@@ -233,16 +233,9 @@ XZ_SRCS = \
        ../src/xz/suffix.c \
        ../src/xz/util.c
 
-XZ_SRCS_FIXED = $(XZ_SRCS:.c=-fixed.c)
 XZ_OBJS = $(XZ_SRCS:.c=.o)
 
-$(XZ_SRCS_FIXED): %-fixed.c: %.c
-       $(SED) "s/%'/%/g" $< > $@
-
-# We need to "fix" the source files which use ' as format character
-# in printf() to get thousand separators. DJGPP doesn't support it.
-# It's not in C89 or C99, but it is in POSIX.
-$(XZ_OBJS): %.o: %-fixed.c
+$(XZ_OBJS): %.o: %.c
        $(CC) $(ALL_CPPFLAGS) $(ALL_CFLAGS) -c -o $@ $<
 
 xz.exe: getopt.a liblzma.a $(XZ_OBJS)
@@ -258,8 +251,5 @@ xz.exe: getopt.a liblzma.a $(XZ_OBJS)
 xz-clean: $(XZ_OBJS:.o=-clean)
        -$(RM) xz.exe xz
 
-# FIXME: Deleting hardware-fixed.c may actually delete hardware.c
-# on Dosemu 1.4.0 with its FreeDOS 1.0. Maybe it tries with
-# truncated 8.3 name first.
 $(XZ_OBJS:.o=-clean):
-       -$(RM) $(@:-clean=.o) $(@:-clean=-fixed.c)
+       -$(RM) $(@:-clean=.o)
index 1d9cb76..8fa06e1 100644 (file)
@@ -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"),
index 7a3c414..0731ad9 100644 (file)
@@ -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)
index d200bfc..d160ea0 100644 (file)
 #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
 ///
index 511d2ee..3657eb8 100644 (file)
@@ -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);
 
index 2da3450..192348b 100644 (file)
@@ -283,24 +283,17 @@ XZ_SRCS = \
        ../src/xz/suffix.c \
        ../src/xz/util.c
 
-XZ_SRCS_FIXED = $(XZ_SRCS:.c=-fixed.c)
 XZ_OBJS = $(XZ_SRCS:.c=.o)
 XZ_OBJS_STATIC = $(XZ_SRCS:.c=-static.o)
 
-$(XZ_SRCS_FIXED): %-fixed.c: %.c
-       $(SED) "s/%'/%/g" $< > $@
-
-# We need to "fix" the source files which use ' as format character
-# in printf() to get thousand separators. Windows doesn't support it.
-# It's not in C89 or C99, but it is in POSIX.
-$(XZ_OBJS): %.o: %-fixed.c
+$(XZ_OBJS): %.o: %.c
        $(CC) $(ALL_CPPFLAGS) $(ALL_CFLAGS) -c -o $@ $<
 
 xz-dynamic.exe: liblzma.dll $(XZ_OBJS) xz_rc.o
        $(CC) $(ALL_CFLAGS) $(XZ_OBJS) xz_rc.o -o $@ liblzma.a
        $(STRIP) --strip-all $@
 
-$(XZ_OBJS_STATIC): %-static.o: %-fixed.c
+$(XZ_OBJS_STATIC): %-static.o: %.c
        $(CC) -DLZMA_API_STATIC $(ALL_CPPFLAGS) $(ALL_CFLAGS) -c -o $@ $<
 
 xz.exe: liblzma_static.lib $(XZ_OBJS_STATIC) xz_rc.o
@@ -309,4 +302,4 @@ xz.exe: liblzma_static.lib $(XZ_OBJS_STATIC) xz_rc.o
 
 .PHONY: xz-clean
 xz-clean:
-       -$(RM) $(XZ_OBJS) $(XZ_OBJS_STATIC) $(XZ_SRCS_FIXED) xz_rc.o xz-dynamic.exe xz.exe
+       -$(RM) $(XZ_OBJS) $(XZ_OBJS_STATIC) xz_rc.o xz-dynamic.exe xz.exe