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.
This commit is contained in:
parent
fe378d4707
commit
cad62551c5
14
dos/Makefile
14
dos/Makefile
|
@ -233,16 +233,9 @@ XZ_SRCS = \
|
||||||
../src/xz/suffix.c \
|
../src/xz/suffix.c \
|
||||||
../src/xz/util.c
|
../src/xz/util.c
|
||||||
|
|
||||||
XZ_SRCS_FIXED = $(XZ_SRCS:.c=-fixed.c)
|
|
||||||
XZ_OBJS = $(XZ_SRCS:.c=.o)
|
XZ_OBJS = $(XZ_SRCS:.c=.o)
|
||||||
|
|
||||||
$(XZ_SRCS_FIXED): %-fixed.c: %.c
|
$(XZ_OBJS): %.o: %.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
|
|
||||||
$(CC) $(ALL_CPPFLAGS) $(ALL_CFLAGS) -c -o $@ $<
|
$(CC) $(ALL_CPPFLAGS) $(ALL_CFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
xz.exe: getopt.a liblzma.a $(XZ_OBJS)
|
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)
|
xz-clean: $(XZ_OBJS:.o=-clean)
|
||||||
-$(RM) xz.exe xz
|
-$(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):
|
$(XZ_OBJS:.o=-clean):
|
||||||
-$(RM) $(@:-clean=.o) $(@:-clean=-fixed.c)
|
-$(RM) $(@:-clean=.o)
|
||||||
|
|
|
@ -363,21 +363,22 @@ progress_sizes_helper(char **pos, size_t *left, uint64_t value, bool final)
|
||||||
if (final) {
|
if (final) {
|
||||||
// At maximum of four digits is allowed for exact byte count.
|
// At maximum of four digits is allowed for exact byte count.
|
||||||
if (value < 10000) {
|
if (value < 10000) {
|
||||||
my_snprintf(pos, left, "%'" PRIu64 " B", value);
|
my_snprintf(pos, left, "%s B",
|
||||||
|
uint64_to_str(value, 0));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// At maximum of five significant digits is allowed for KiB.
|
// At maximum of five significant digits is allowed for KiB.
|
||||||
if (value < UINT64_C(10239900)) {
|
if (value < UINT64_C(10239900)) {
|
||||||
my_snprintf(pos, left, "%'.1f KiB",
|
my_snprintf(pos, left, "%s KiB", double_to_str(
|
||||||
(double)(value) / 1024.0);
|
(double)(value) / 1024.0));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise we use MiB.
|
// Otherwise we use MiB.
|
||||||
my_snprintf(pos, left, "%'.1f MiB",
|
my_snprintf(pos, left, "%s MiB",
|
||||||
(double)(value) / (1024.0 * 1024.0));
|
double_to_str((double)(value) / (1024.0 * 1024.0)));
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1157,10 +1158,10 @@ message_help(bool long_help)
|
||||||
if (long_help) {
|
if (long_help) {
|
||||||
printf(_(
|
printf(_(
|
||||||
"On this system and configuration, this program will use at maximum of roughly\n"
|
"On this system and configuration, this program will use at maximum of roughly\n"
|
||||||
"%'" PRIu64 " MiB RAM and "), hardware_memlimit_get() / (1024 * 1024));
|
"%s MiB RAM and "), uint64_to_str(hardware_memlimit_get() / (1024 * 1024), 0));
|
||||||
printf(N_("one thread.\n\n", "%'" PRIu32 " threads.\n\n",
|
printf(N_("one thread.\n\n", "%s threads.\n\n",
|
||||||
hardware_threadlimit_get()),
|
hardware_threadlimit_get()),
|
||||||
hardware_threadlimit_get());
|
uint64_to_str(hardware_threadlimit_get(), 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
printf(_("Report bugs to <%s> (in English or Finnish).\n"),
|
printf(_("Report bugs to <%s> (in English or Finnish).\n"),
|
||||||
|
|
|
@ -163,11 +163,12 @@ coder_set_compression_settings(void)
|
||||||
message_fatal("Unsupported filter chain or filter options");
|
message_fatal("Unsupported filter chain or filter options");
|
||||||
|
|
||||||
// Print memory usage info.
|
// Print memory usage info.
|
||||||
message(V_DEBUG, _("%'" PRIu64 " MiB (%'" PRIu64 " B) of memory is "
|
message(V_DEBUG, _("%s MiB (%s B) of memory is required per thread, "
|
||||||
"required per thread, "
|
"limit is %s MiB (%s B)"),
|
||||||
"limit is %'" PRIu64 " MiB (%'" PRIu64 " B)"),
|
uint64_to_str(memory_usage >> 20, 0),
|
||||||
memory_usage >> 20, memory_usage,
|
uint64_to_str(memory_usage, 1),
|
||||||
memory_limit >> 20, memory_limit);
|
uint64_to_str(memory_limit >> 20, 2),
|
||||||
|
uint64_to_str(memory_limit, 3));
|
||||||
|
|
||||||
if (memory_usage > memory_limit) {
|
if (memory_usage > memory_limit) {
|
||||||
// If --no-auto-adjust was used or we didn't find LZMA1 or
|
// 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?
|
// was given. FIXME: Always warn?
|
||||||
if (!preset_default)
|
if (!preset_default)
|
||||||
message(V_WARNING, "Adjusted LZMA%c dictionary size "
|
message(V_WARNING, "Adjusted LZMA%c dictionary size "
|
||||||
"from %'" PRIu32 " MiB to "
|
"from %s MiB to %s MiB to not exceed "
|
||||||
"%'" PRIu32 " MiB to not exceed "
|
"the memory usage limit of %s MiB",
|
||||||
"the memory usage limit of "
|
|
||||||
"%'" PRIu64 " MiB",
|
|
||||||
filters[i].id == LZMA_FILTER_LZMA2
|
filters[i].id == LZMA_FILTER_LZMA2
|
||||||
? '2' : '1',
|
? '2' : '1',
|
||||||
orig_dict_size >> 20,
|
uint64_to_str(orig_dict_size >> 20, 0),
|
||||||
opt->dict_size >> 20,
|
uint64_to_str(opt->dict_size >> 20, 1),
|
||||||
memory_limit >> 20);
|
uint64_to_str(memory_limit >> 20, 2));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -443,10 +442,11 @@ coder_run(file_pair *pair)
|
||||||
/ (1024 * 1024);
|
/ (1024 * 1024);
|
||||||
memlimit /= 1024 * 1024;
|
memlimit /= 1024 * 1024;
|
||||||
|
|
||||||
message_error(_("Limit was %'" PRIu64 " MiB, "
|
message_error(_("Limit was %s MiB, "
|
||||||
"but %'" PRIu64 " MiB would "
|
"but %s MiB would "
|
||||||
"have been needed"),
|
"have been needed"),
|
||||||
memlimit, memusage);
|
uint64_to_str(memlimit, 0),
|
||||||
|
uint64_to_str(memusage, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stop)
|
if (stop)
|
||||||
|
|
|
@ -13,6 +13,15 @@
|
||||||
#include "private.h"
|
#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 *
|
extern void *
|
||||||
xrealloc(void *ptr, size_t size)
|
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
|
/// \brief Simple quoting to get rid of ASCII control characters
|
||||||
///
|
///
|
||||||
|
|
|
@ -41,6 +41,26 @@ extern uint64_t str_to_uint64(const char *name, const char *value,
|
||||||
uint64_t min, uint64_t max);
|
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
|
/// \brief Check if filename is empty and print an error message
|
||||||
extern bool is_empty_filename(const char *filename);
|
extern bool is_empty_filename(const char *filename);
|
||||||
|
|
||||||
|
|
|
@ -283,24 +283,17 @@ XZ_SRCS = \
|
||||||
../src/xz/suffix.c \
|
../src/xz/suffix.c \
|
||||||
../src/xz/util.c
|
../src/xz/util.c
|
||||||
|
|
||||||
XZ_SRCS_FIXED = $(XZ_SRCS:.c=-fixed.c)
|
|
||||||
XZ_OBJS = $(XZ_SRCS:.c=.o)
|
XZ_OBJS = $(XZ_SRCS:.c=.o)
|
||||||
XZ_OBJS_STATIC = $(XZ_SRCS:.c=-static.o)
|
XZ_OBJS_STATIC = $(XZ_SRCS:.c=-static.o)
|
||||||
|
|
||||||
$(XZ_SRCS_FIXED): %-fixed.c: %.c
|
$(XZ_OBJS): %.o: %.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
|
|
||||||
$(CC) $(ALL_CPPFLAGS) $(ALL_CFLAGS) -c -o $@ $<
|
$(CC) $(ALL_CPPFLAGS) $(ALL_CFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
xz-dynamic.exe: liblzma.dll $(XZ_OBJS) xz_rc.o
|
xz-dynamic.exe: liblzma.dll $(XZ_OBJS) xz_rc.o
|
||||||
$(CC) $(ALL_CFLAGS) $(XZ_OBJS) xz_rc.o -o $@ liblzma.a
|
$(CC) $(ALL_CFLAGS) $(XZ_OBJS) xz_rc.o -o $@ liblzma.a
|
||||||
$(STRIP) --strip-all $@
|
$(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 $@ $<
|
$(CC) -DLZMA_API_STATIC $(ALL_CPPFLAGS) $(ALL_CFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
xz.exe: liblzma_static.lib $(XZ_OBJS_STATIC) xz_rc.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
|
.PHONY: xz-clean
|
||||||
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
|
||||||
|
|
Loading…
Reference in New Issue